mirror of
https://github.com/spl0k/supysonic.git
synced 2025-01-12 11:16:18 +00:00
Folders management got its own module
This commit is contained in:
parent
7dbd1f9764
commit
db2694352e
118
folder.py
Executable file
118
folder.py
Executable file
@ -0,0 +1,118 @@
|
|||||||
|
# coding: utf-8
|
||||||
|
|
||||||
|
from flask import request, flash, render_template, redirect, url_for
|
||||||
|
import os.path
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from web import app
|
||||||
|
from db import session, Folder, Artist
|
||||||
|
from scanner import Scanner
|
||||||
|
|
||||||
|
@app.route('/folder')
|
||||||
|
def folder_index():
|
||||||
|
return render_template('folders.html', folders = Folder.query.filter(Folder.root == True).all())
|
||||||
|
|
||||||
|
@app.route('/folder/add', methods = [ 'GET', 'POST' ])
|
||||||
|
def add_folder():
|
||||||
|
if request.method == 'GET':
|
||||||
|
return render_template('addfolder.html')
|
||||||
|
|
||||||
|
error = False
|
||||||
|
(name, path) = map(request.form.get, [ 'name', 'path' ])
|
||||||
|
if name in (None, ''):
|
||||||
|
flash('The name is required.')
|
||||||
|
error = True
|
||||||
|
elif Folder.query.filter(Folder.name == name and Folder.root).first():
|
||||||
|
flash('There is already a folder with that name. Please pick another one.')
|
||||||
|
error = True
|
||||||
|
if path in (None, ''):
|
||||||
|
flash('The path is required.')
|
||||||
|
error = True
|
||||||
|
else:
|
||||||
|
path = os.path.abspath(path)
|
||||||
|
if not os.path.isdir(path):
|
||||||
|
flash("The path '%s' doesn't exists or isn't a directory" % path)
|
||||||
|
error = True
|
||||||
|
folder = Folder.query.filter(Folder.path == path).first()
|
||||||
|
if folder:
|
||||||
|
flash("This path is already registered")
|
||||||
|
error = True
|
||||||
|
if error:
|
||||||
|
return render_template('addfolder.html')
|
||||||
|
|
||||||
|
folder = Folder(root = True, name = name, path = path)
|
||||||
|
session.add(folder)
|
||||||
|
session.commit()
|
||||||
|
flash("Folder '%s' created. You should now run a scan" % name)
|
||||||
|
|
||||||
|
return redirect(url_for('folder_index'))
|
||||||
|
|
||||||
|
@app.route('/folder/del/<id>')
|
||||||
|
def del_folder(id):
|
||||||
|
try:
|
||||||
|
idid = uuid.UUID(id)
|
||||||
|
except ValueError:
|
||||||
|
flash('Invalid folder id')
|
||||||
|
return redirect(url_for('folder_index'))
|
||||||
|
|
||||||
|
folder = Folder.query.get(idid)
|
||||||
|
if folder is None or not folder.root:
|
||||||
|
flash('No such folder')
|
||||||
|
return redirect(url_for('folder_index'))
|
||||||
|
|
||||||
|
# delete associated tracks and prune empty albums/artists
|
||||||
|
for artist in Artist.query.all():
|
||||||
|
for album in artist.albums[:]:
|
||||||
|
for track in filter(lambda t: t.root_folder.id == folder.id, album.tracks):
|
||||||
|
album.tracks.remove(track)
|
||||||
|
session.delete(track)
|
||||||
|
if len(album.tracks) == 0:
|
||||||
|
artist.albums.remove(album)
|
||||||
|
session.delete(album)
|
||||||
|
if len(artist.albums) == 0:
|
||||||
|
session.delete(artist)
|
||||||
|
|
||||||
|
def cleanup_folder(folder):
|
||||||
|
for f in folder.children:
|
||||||
|
cleanup_folder(f)
|
||||||
|
session.delete(folder)
|
||||||
|
|
||||||
|
cleanup_folder(folder)
|
||||||
|
|
||||||
|
session.commit()
|
||||||
|
flash("Deleted folder '%s'" % folder.name)
|
||||||
|
|
||||||
|
return redirect(url_for('folder_index'))
|
||||||
|
|
||||||
|
@app.route('/folder/scan')
|
||||||
|
@app.route('/folder/scan/<id>')
|
||||||
|
def scan_folder(id = None):
|
||||||
|
s = Scanner(session)
|
||||||
|
if id is None:
|
||||||
|
for folder in Folder.query.filter(Folder.root == True).all():
|
||||||
|
s.scan(folder)
|
||||||
|
s.prune(folder)
|
||||||
|
s.check_cover_art(folder)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
idid = uuid.UUID(id)
|
||||||
|
except ValueError:
|
||||||
|
flash('Invalid folder id')
|
||||||
|
return redirect(url_for('folder_index'))
|
||||||
|
|
||||||
|
folder = Folder.query.get(idid)
|
||||||
|
if folder is None or not folder.root:
|
||||||
|
flash('No such folder')
|
||||||
|
return redirect(url_for('folder_index'))
|
||||||
|
|
||||||
|
s.scan(folder)
|
||||||
|
s.prune(folder)
|
||||||
|
s.check_cover_art(folder)
|
||||||
|
|
||||||
|
added, deleted = s.stats()
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
flash('Added: %i artists, %i albums, %i tracks' % (added[0], added[1], added[2]))
|
||||||
|
flash('Deleted: %i artists, %i albums, %i tracks' % (deleted[0], deleted[1], deleted[2]))
|
||||||
|
return redirect(url_for('folder_index'))
|
||||||
|
|
14
templates/folders.html
Executable file
14
templates/folders.html
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block body %}
|
||||||
|
<h2>Music folders</h2>
|
||||||
|
<table>
|
||||||
|
<tr><th>Name</th><th>Path</th><th></th><th></th></tr>
|
||||||
|
{% for folder in folders %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ folder.name }}</td><td>{{ folder.path }}</td><td><a href="{{ url_for('del_folder', id = folder.id) }}">X</a></td>
|
||||||
|
<td><a href="{{ url_for('scan_folder', id = folder.id) }}">Scan</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
<a href="{{ url_for('add_folder') }}">Add</a> <a href="{{ url_for('scan_folder') }}">Scan all</a>
|
||||||
|
{% endblock %}
|
@ -1,18 +1,6 @@
|
|||||||
{% extends "layout.html" %}
|
{% extends "layout.html" %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<p><a href="{{ url_for('user_index') }}">Users</a></p>
|
<p><a href="{{ url_for('user_index') }}">Users</a> | <a href="{{ url_for('folder_index') }}">Folders</a></p>
|
||||||
|
|
||||||
<h2>Music folders</h2>
|
|
||||||
<table>
|
|
||||||
<tr><th>Name</th><th>Path</th><th></th><th></th></tr>
|
|
||||||
{% for folder in folders %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ folder.name }}</td><td>{{ folder.path }}</td><td><a href="{{ url_for('del_folder', id = folder.id) }}">X</a></td>
|
|
||||||
<td><a href="{{ url_for('scan_folder', id = folder.id) }}">Scan</a></td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
<a href="{{ url_for('add_folder') }}">Add</a> <a href="{{ url_for('scan_folder') }}">Scan all</a>
|
|
||||||
|
|
||||||
<h2>Artists</h2>
|
<h2>Artists</h2>
|
||||||
<table>
|
<table>
|
||||||
|
8
user.py
8
user.py
@ -1,14 +1,14 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
from flask import Flask, request, session, flash, render_template, redirect, url_for
|
from flask import request, session, flash, render_template, redirect, url_for
|
||||||
|
|
||||||
from web import app
|
from web import app
|
||||||
from user_manager import UserManager
|
from user_manager import UserManager
|
||||||
import db
|
from db import User
|
||||||
|
|
||||||
@app.route('/user')
|
@app.route('/user')
|
||||||
def user_index():
|
def user_index():
|
||||||
return render_template('users.html', users = db.User.query.all())
|
return render_template('users.html', users = User.query.all())
|
||||||
|
|
||||||
@app.route('/user/add', methods = [ 'GET', 'POST' ])
|
@app.route('/user/add', methods = [ 'GET', 'POST' ])
|
||||||
def add_user():
|
def add_user():
|
||||||
@ -28,7 +28,7 @@ def add_user():
|
|||||||
error = True
|
error = True
|
||||||
|
|
||||||
if admin is None:
|
if admin is None:
|
||||||
admin = True if db.User.query.filter(db.User.admin == True).count() == 0 else False
|
admin = True if User.query.filter(User.admin == True).count() == 0 else False
|
||||||
else:
|
else:
|
||||||
admin = True
|
admin = True
|
||||||
|
|
||||||
|
110
web.py
110
web.py
@ -1,14 +1,11 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
from flask import Flask, request, session, flash, render_template, redirect, url_for
|
from flask import Flask, request, session, flash, render_template, redirect, url_for
|
||||||
import os.path
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.secret_key = '?9huDM\\H'
|
app.secret_key = '?9huDM\\H'
|
||||||
|
|
||||||
import db
|
import db
|
||||||
from scanner import Scanner
|
|
||||||
from user_manager import UserManager
|
from user_manager import UserManager
|
||||||
|
|
||||||
@app.before_request
|
@app.before_request
|
||||||
@ -39,7 +36,7 @@ def teardown(exception):
|
|||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
return render_template('home.html', folders = db.Folder.query.filter(db.Folder.root == True).all(),
|
return render_template('home.html',
|
||||||
artists = db.Artist.query.order_by(db.Artist.name).all(),
|
artists = db.Artist.query.order_by(db.Artist.name).all(),
|
||||||
albums = db.Album.query.join(db.Album.artist).order_by(db.Artist.name, db.Album.name).all())
|
albums = db.Album.query.join(db.Album.artist).order_by(db.Artist.name, db.Album.name).all())
|
||||||
|
|
||||||
@ -48,111 +45,8 @@ def reset_db():
|
|||||||
db.recreate_db()
|
db.recreate_db()
|
||||||
return redirect(url_for('index'))
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
@app.route('/addfolder', methods = [ 'GET', 'POST' ])
|
|
||||||
def add_folder():
|
|
||||||
if request.method == 'GET':
|
|
||||||
return render_template('addfolder.html')
|
|
||||||
|
|
||||||
error = False
|
|
||||||
(name, path) = map(request.form.get, [ 'name', 'path' ])
|
|
||||||
if name in (None, ''):
|
|
||||||
flash('The name is required.')
|
|
||||||
error = True
|
|
||||||
elif db.Folder.query.filter(db.Folder.name == name and db.Folder.root).first():
|
|
||||||
flash('There is already a folder with that name. Please pick another one.')
|
|
||||||
error = True
|
|
||||||
if path in (None, ''):
|
|
||||||
flash('The path is required.')
|
|
||||||
error = True
|
|
||||||
else:
|
|
||||||
path = os.path.abspath(path)
|
|
||||||
if not os.path.isdir(path):
|
|
||||||
flash("The path '%s' doesn't exists or isn't a directory" % path)
|
|
||||||
error = True
|
|
||||||
folder = db.Folder.query.filter(db.Folder.path == path).first()
|
|
||||||
if folder:
|
|
||||||
flash("This path is already registered")
|
|
||||||
error = True
|
|
||||||
if error:
|
|
||||||
return render_template('addfolder.html')
|
|
||||||
|
|
||||||
folder = db.Folder(root = True, name = name, path = path)
|
|
||||||
db.session.add(folder)
|
|
||||||
db.session.commit()
|
|
||||||
flash("Folder '%s' created. You should now run a scan" % name)
|
|
||||||
|
|
||||||
return redirect(url_for('index'))
|
|
||||||
|
|
||||||
@app.route('/delfolder/<id>')
|
|
||||||
def del_folder(id):
|
|
||||||
try:
|
|
||||||
idid = uuid.UUID(id)
|
|
||||||
except ValueError:
|
|
||||||
flash('Invalid folder id')
|
|
||||||
return redirect(url_for('index'))
|
|
||||||
|
|
||||||
folder = db.Folder.query.get(idid)
|
|
||||||
if folder is None:
|
|
||||||
flash('No such folder')
|
|
||||||
return redirect(url_for('index'))
|
|
||||||
|
|
||||||
# delete associated tracks and prune empty albums/artists
|
|
||||||
for artist in db.Artist.query.all():
|
|
||||||
for album in artist.albums[:]:
|
|
||||||
for track in filter(lambda t: t.root_folder.id == folder.id, album.tracks):
|
|
||||||
album.tracks.remove(track)
|
|
||||||
db.session.delete(track)
|
|
||||||
if len(album.tracks) == 0:
|
|
||||||
artist.albums.remove(album)
|
|
||||||
db.session.delete(album)
|
|
||||||
if len(artist.albums) == 0:
|
|
||||||
db.session.delete(artist)
|
|
||||||
|
|
||||||
def cleanup_folder(folder):
|
|
||||||
for f in folder.children:
|
|
||||||
cleanup_folder(f)
|
|
||||||
db.session.delete(folder)
|
|
||||||
|
|
||||||
cleanup_folder(folder)
|
|
||||||
|
|
||||||
db.session.commit()
|
|
||||||
flash("Deleted folder '%s'" % folder.name)
|
|
||||||
|
|
||||||
return redirect(url_for('index'))
|
|
||||||
|
|
||||||
@app.route('/scan')
|
|
||||||
@app.route('/scan/<id>')
|
|
||||||
def scan_folder(id = None):
|
|
||||||
s = Scanner(db.session)
|
|
||||||
if id is None:
|
|
||||||
for folder in db.Folder.query.filter(db.Folder.root == True).all():
|
|
||||||
s.scan(folder)
|
|
||||||
s.prune(folder)
|
|
||||||
s.check_cover_art(folder)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
idid = uuid.UUID(id)
|
|
||||||
except ValueError:
|
|
||||||
flash('Invalid folder id')
|
|
||||||
return redirect(url_for('index'))
|
|
||||||
|
|
||||||
folder = db.Folder.query.get(idid)
|
|
||||||
if folder is None or not folder.root:
|
|
||||||
flash('No such folder')
|
|
||||||
return redirect(url_for('index'))
|
|
||||||
|
|
||||||
s.scan(folder)
|
|
||||||
s.prune(folder)
|
|
||||||
s.check_cover_art(folder)
|
|
||||||
|
|
||||||
added, deleted = s.stats()
|
|
||||||
db.session.commit()
|
|
||||||
|
|
||||||
flash('Added: %i artists, %i albums, %i tracks' % (added[0], added[1], added[2]))
|
|
||||||
flash('Deleted: %i artists, %i albums, %i tracks' % (deleted[0], deleted[1], deleted[2]))
|
|
||||||
return redirect(url_for('index'))
|
|
||||||
|
|
||||||
import user
|
import user
|
||||||
|
import folder
|
||||||
|
|
||||||
import api.system
|
import api.system
|
||||||
import api.browse
|
import api.browse
|
||||||
|
Loading…
Reference in New Issue
Block a user