1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-12-22 17:06:17 +00:00

Web UI now scans in background

This commit is contained in:
spl0k 2019-04-22 17:48:44 +02:00
parent 7bbbdac41c
commit e210f25bb3
4 changed files with 47 additions and 45 deletions

View File

@ -3,16 +3,18 @@
# This file is part of Supysonic.
# Supysonic is a Python implementation of the Subsonic server API.
#
# Copyright (C) 2013-2018 Alban 'spl0k' Féron
# Copyright (C) 2013-2019 Alban 'spl0k' Féron
# 2017 Óscar García Amor
#
# Distributed under terms of the GNU AGPLv3 license.
from flask import redirect, request, session, url_for
from flask import current_app, redirect, request, session, url_for
from flask import Blueprint
from functools import wraps
from pony.orm import ObjectNotFound
from ..daemon.client import DaemonClient
from ..daemon.exceptions import DaemonUnavailableError
from ..db import Artist, Album, Track
from ..managers.user import UserManager
@ -34,6 +36,18 @@ def login_check():
flash('Please login')
return redirect(url_for('frontend.login', returnUrl = request.script_root + request.url[len(request.url_root)-1:]))
@frontend.before_request
def scan_status():
if not request.user or not request.user.admin:
return
try:
scanned = DaemonClient(current_app.config['DAEMON']['socket']).get_scanning_progress()
if scanned is not None:
flash('Scanning in progress, {} files scanned.'.format(scanned))
except DaemonUnavailableError:
pass
@frontend.route('/')
def index():
stats = {

View File

@ -3,7 +3,7 @@
# This file is part of Supysonic.
# Supysonic is a Python implementation of the Subsonic server API.
#
# Copyright (C) 2013-2018 Alban 'spl0k' Féron
# Copyright (C) 2013-2019 Alban 'spl0k' Féron
#
# Distributed under terms of the GNU AGPLv3 license.
@ -13,6 +13,8 @@ import uuid
from flask import current_app, flash, redirect, render_template, request, url_for
from pony.orm import ObjectNotFound
from ..daemon.client import DaemonClient
from ..daemon.exceptions import DaemonUnavailableError
from ..db import Folder
from ..managers.folder import FolderManager
from ..scanner import Scanner
@ -22,7 +24,13 @@ from . import admin_only, frontend
@frontend.route('/folder')
@admin_only
def folder_index():
return render_template('folders.html', folders = Folder.select(lambda f: f.root))
try:
DaemonClient(current_app.config['DAEMON']['socket']).get_scanning_progress()
allow_scan = True
except DaemonUnavailableError:
allow_scan = False
flash("The daemon is unavailable, can't scan from the web interface, use the CLI to do so.", 'warning')
return render_template('folders.html', folders = Folder.select(lambda f: f.root), allow_scan = allow_scan)
@frontend.route('/folder/add')
@admin_only
@ -69,35 +77,18 @@ def del_folder(id):
@frontend.route('/folder/scan/<id>')
@admin_only
def scan_folder(id = None):
extensions = current_app.config['BASE']['scanner_extensions']
if extensions:
extensions = extensions.split(' ')
try:
if id is not None:
folders = [ FolderManager.get(id).name ]
else:
folders = []
DaemonClient(current_app.config['DAEMON']['socket']).scan(folders)
flash('Scanning started')
except ValueError as e:
flash(str(e), 'error')
except ObjectNotFound:
flash('No such folder', 'error')
except DaemonUnavailableError:
flash("Can't start scan", 'error')
scanner = Scanner(extensions = extensions)
if id is None:
for folder in Folder.select(lambda f: f.root):
scanner.scan(folder)
else:
try:
folder = FolderManager.get(id)
except ValueError as e:
flash(str(e), 'error')
return redirect(url_for('frontend.folder_index'))
except ObjectNotFound:
flash('No such folder', 'error')
return redirect(url_for('frontend.folder_index'))
scanner.scan(folder)
scanner.finish()
stats = scanner.stats()
flash('Added: {0.artists} artists, {0.albums} albums, {0.tracks} tracks'.format(stats.added))
flash('Deleted: {0.artists} artists, {0.albums} albums, {0.tracks} tracks'.format(stats.deleted))
if stats.errors:
flash('Errors in:')
for err in stats.errors:
flash('- ' + err)
return redirect(url_for('frontend.folder_index'))

View File

@ -2,7 +2,7 @@
This file is part of Supysonic.
Supysonic is a Python implementation of the Subsonic server API.
Copyright (C) 2013-2018 Alban 'spl0k' Féron
Copyright (C) 2013-2019 Alban 'spl0k' Féron
2017 Óscar García Amor
Distributed under terms of the GNU AGPLv3 license.
@ -18,7 +18,7 @@
</div>
<table class="table table-striped table-hover">
<thead>
<tr><th>Name</th><th>Path</th><th></th><th></th></tr>
<tr><th>Name</th><th>Path</th><th></th>{% if allow_scan %}<th></th>{% endif %}</tr>
</thead>
<tbody>
{% for folder in folders %}
@ -26,15 +26,15 @@
<td>{{ folder.name }}</td><td>{{ folder.path }}</td><td>
<button class="btn btn-danger btn-xs" data-href="{{ url_for('frontend.del_folder', id = folder.id) }}" data-toggle="modal" data-target="#confirm-delete" aria-label="Delete folder">
<span class="glyphicon glyphicon-remove-circle" aria-hidden="true" data-toggle="tooltip" data-placement="top" title="Delete folder"></span></button></td>
<td><a class="btn btn-default btn-xs" href="{{ url_for('frontend.scan_folder', id = folder.id) }}" aria-label="Scan folder">
<span class="glyphicon glyphicon-search" aria-hidden="true" data-toggle="tooltip" data-placement="top" title="Scan folder"></span></a></td>
{%if allow_scan %}<td><a class="btn btn-default btn-xs" href="{{ url_for('frontend.scan_folder', id = folder.id) }}" aria-label="Scan folder">
<span class="glyphicon glyphicon-search" aria-hidden="true" data-toggle="tooltip" data-placement="top" title="Scan folder"></span></a></td>{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
<div class="btn-toolbar" role="toolbar">
<a href="{{ url_for('frontend.add_folder_form') }}" class="btn btn-default">Add</a>
<a href="{{ url_for('frontend.scan_folder') }}" class="btn btn-default">Scan all</a>
{% if allow_scan %}<a href="{{ url_for('frontend.scan_folder') }}" class="btn btn-default">Scan all</a>{% endif %}
</div>
<div class="modal fade" id="confirm-delete" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">

View File

@ -4,7 +4,7 @@
# This file is part of Supysonic.
# Supysonic is a Python implementation of the Subsonic server API.
#
# Copyright (C) 2017-2018 Alban 'spl0k' Féron
# Copyright (C) 2017-2019 Alban 'spl0k' Féron
#
# Distributed under terms of the GNU AGPLv3 license.
@ -94,12 +94,9 @@ class FolderTestCase(FrontendTestBase):
rv = self.client.get('/folder/scan/' + str(uuid.uuid4()), follow_redirects = True)
self.assertIn('No such folder', rv.data)
rv = self.client.get('/folder/scan/' + str(folder.id), follow_redirects = True)
self.assertIn('Added', rv.data)
self.assertIn('Deleted', rv.data)
self.assertIn('start', rv.data)
rv = self.client.get('/folder/scan', follow_redirects = True)
self.assertIn('Added', rv.data)
self.assertIn('Deleted', rv.data)
self.assertIn('start', rv.data)
if __name__ == '__main__':
unittest.main()