mirror of
https://github.com/clinton-hall/nzbToMedia.git
synced 2025-08-14 10:36:52 -07:00
Update vendored beets to 1.6.0
Updates colorama to 0.4.6 Adds confuse version 1.7.0 Updates jellyfish to 0.9.0 Adds mediafile 0.10.1 Updates munkres to 1.1.4 Updates musicbrainzngs to 0.7.1 Updates mutagen to 1.46.0 Updates pyyaml to 6.0 Updates unidecode to 1.3.6
This commit is contained in:
parent
5073ec0c6f
commit
56c6773c6b
385 changed files with 25143 additions and 18080 deletions
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# This file is part of beets.
|
||||
# Copyright 2016, Adrian Sampson.
|
||||
#
|
||||
|
@ -14,14 +13,13 @@
|
|||
# included in all copies or substantial portions of the Software.
|
||||
|
||||
"""A Web interface to beets."""
|
||||
from __future__ import division, absolute_import, print_function
|
||||
|
||||
from beets.plugins import BeetsPlugin
|
||||
from beets import ui
|
||||
from beets import util
|
||||
import beets.library
|
||||
import flask
|
||||
from flask import g
|
||||
from flask import g, jsonify
|
||||
from werkzeug.routing import BaseConverter, PathConverter
|
||||
import os
|
||||
from unidecode import unidecode
|
||||
|
@ -59,7 +57,10 @@ def _rep(obj, expand=False):
|
|||
return out
|
||||
|
||||
elif isinstance(obj, beets.library.Album):
|
||||
del out['artpath']
|
||||
if app.config.get('INCLUDE_PATHS', False):
|
||||
out['artpath'] = util.displayable_path(out['artpath'])
|
||||
else:
|
||||
del out['artpath']
|
||||
if expand:
|
||||
out['items'] = [_rep(item) for item in obj.items()]
|
||||
return out
|
||||
|
@ -91,7 +92,20 @@ def is_expand():
|
|||
return flask.request.args.get('expand') is not None
|
||||
|
||||
|
||||
def resource(name):
|
||||
def is_delete():
|
||||
"""Returns whether the current delete request should remove the selected
|
||||
files.
|
||||
"""
|
||||
|
||||
return flask.request.args.get('delete') is not None
|
||||
|
||||
|
||||
def get_method():
|
||||
"""Returns the HTTP method of the current request."""
|
||||
return flask.request.method
|
||||
|
||||
|
||||
def resource(name, patchable=False):
|
||||
"""Decorates a function to handle RESTful HTTP requests for a resource.
|
||||
"""
|
||||
def make_responder(retriever):
|
||||
|
@ -99,34 +113,98 @@ def resource(name):
|
|||
entities = [retriever(id) for id in ids]
|
||||
entities = [entity for entity in entities if entity]
|
||||
|
||||
if len(entities) == 1:
|
||||
return flask.jsonify(_rep(entities[0], expand=is_expand()))
|
||||
elif entities:
|
||||
return app.response_class(
|
||||
json_generator(entities, root=name),
|
||||
mimetype='application/json'
|
||||
)
|
||||
if get_method() == "DELETE":
|
||||
|
||||
if app.config.get('READONLY', True):
|
||||
return flask.abort(405)
|
||||
|
||||
for entity in entities:
|
||||
entity.remove(delete=is_delete())
|
||||
|
||||
return flask.make_response(jsonify({'deleted': True}), 200)
|
||||
|
||||
elif get_method() == "PATCH" and patchable:
|
||||
if app.config.get('READONLY', True):
|
||||
return flask.abort(405)
|
||||
|
||||
for entity in entities:
|
||||
entity.update(flask.request.get_json())
|
||||
entity.try_sync(True, False) # write, don't move
|
||||
|
||||
if len(entities) == 1:
|
||||
return flask.jsonify(_rep(entities[0], expand=is_expand()))
|
||||
elif entities:
|
||||
return app.response_class(
|
||||
json_generator(entities, root=name),
|
||||
mimetype='application/json'
|
||||
)
|
||||
|
||||
elif get_method() == "GET":
|
||||
if len(entities) == 1:
|
||||
return flask.jsonify(_rep(entities[0], expand=is_expand()))
|
||||
elif entities:
|
||||
return app.response_class(
|
||||
json_generator(entities, root=name),
|
||||
mimetype='application/json'
|
||||
)
|
||||
else:
|
||||
return flask.abort(404)
|
||||
|
||||
else:
|
||||
return flask.abort(404)
|
||||
responder.__name__ = 'get_{0}'.format(name)
|
||||
return flask.abort(405)
|
||||
|
||||
responder.__name__ = f'get_{name}'
|
||||
|
||||
return responder
|
||||
return make_responder
|
||||
|
||||
|
||||
def resource_query(name):
|
||||
def resource_query(name, patchable=False):
|
||||
"""Decorates a function to handle RESTful HTTP queries for resources.
|
||||
"""
|
||||
def make_responder(query_func):
|
||||
def responder(queries):
|
||||
return app.response_class(
|
||||
json_generator(
|
||||
query_func(queries),
|
||||
root='results', expand=is_expand()
|
||||
),
|
||||
mimetype='application/json'
|
||||
)
|
||||
responder.__name__ = 'query_{0}'.format(name)
|
||||
entities = query_func(queries)
|
||||
|
||||
if get_method() == "DELETE":
|
||||
|
||||
if app.config.get('READONLY', True):
|
||||
return flask.abort(405)
|
||||
|
||||
for entity in entities:
|
||||
entity.remove(delete=is_delete())
|
||||
|
||||
return flask.make_response(jsonify({'deleted': True}), 200)
|
||||
|
||||
elif get_method() == "PATCH" and patchable:
|
||||
if app.config.get('READONLY', True):
|
||||
return flask.abort(405)
|
||||
|
||||
for entity in entities:
|
||||
entity.update(flask.request.get_json())
|
||||
entity.try_sync(True, False) # write, don't move
|
||||
|
||||
return app.response_class(
|
||||
json_generator(entities, root=name),
|
||||
mimetype='application/json'
|
||||
)
|
||||
|
||||
elif get_method() == "GET":
|
||||
return app.response_class(
|
||||
json_generator(
|
||||
entities,
|
||||
root='results', expand=is_expand()
|
||||
),
|
||||
mimetype='application/json'
|
||||
)
|
||||
|
||||
else:
|
||||
return flask.abort(405)
|
||||
|
||||
responder.__name__ = f'query_{name}'
|
||||
|
||||
return responder
|
||||
|
||||
return make_responder
|
||||
|
||||
|
||||
|
@ -140,7 +218,7 @@ def resource_list(name):
|
|||
json_generator(list_all(), root=name, expand=is_expand()),
|
||||
mimetype='application/json'
|
||||
)
|
||||
responder.__name__ = 'all_{0}'.format(name)
|
||||
responder.__name__ = f'all_{name}'
|
||||
return responder
|
||||
return make_responder
|
||||
|
||||
|
@ -150,7 +228,7 @@ def _get_unique_table_field_values(model, field, sort_field):
|
|||
if field not in model.all_keys() or sort_field not in model.all_keys():
|
||||
raise KeyError
|
||||
with g.lib.transaction() as tx:
|
||||
rows = tx.query('SELECT DISTINCT "{0}" FROM "{1}" ORDER BY "{2}"'
|
||||
rows = tx.query('SELECT DISTINCT "{}" FROM "{}" ORDER BY "{}"'
|
||||
.format(field, model._table, sort_field))
|
||||
return [row[0] for row in rows]
|
||||
|
||||
|
@ -169,7 +247,7 @@ class IdListConverter(BaseConverter):
|
|||
return ids
|
||||
|
||||
def to_url(self, value):
|
||||
return ','.join(value)
|
||||
return ','.join(str(v) for v in value)
|
||||
|
||||
|
||||
class QueryConverter(PathConverter):
|
||||
|
@ -177,10 +255,13 @@ class QueryConverter(PathConverter):
|
|||
"""
|
||||
|
||||
def to_python(self, value):
|
||||
return value.split('/')
|
||||
queries = value.split('/')
|
||||
"""Do not do path substitution on regex value tests"""
|
||||
return [query if '::' in query else query.replace('\\', os.sep)
|
||||
for query in queries]
|
||||
|
||||
def to_url(self, value):
|
||||
return ','.join(value)
|
||||
return ','.join([v.replace(os.sep, '\\') for v in value])
|
||||
|
||||
|
||||
class EverythingConverter(PathConverter):
|
||||
|
@ -202,8 +283,8 @@ def before_request():
|
|||
|
||||
# Items.
|
||||
|
||||
@app.route('/item/<idlist:ids>')
|
||||
@resource('items')
|
||||
@app.route('/item/<idlist:ids>', methods=["GET", "DELETE", "PATCH"])
|
||||
@resource('items', patchable=True)
|
||||
def get_item(id):
|
||||
return g.lib.get_item(id)
|
||||
|
||||
|
@ -249,8 +330,8 @@ def item_file(item_id):
|
|||
return response
|
||||
|
||||
|
||||
@app.route('/item/query/<query:queries>')
|
||||
@resource_query('items')
|
||||
@app.route('/item/query/<query:queries>', methods=["GET", "DELETE", "PATCH"])
|
||||
@resource_query('items', patchable=True)
|
||||
def item_query(queries):
|
||||
return g.lib.items(queries)
|
||||
|
||||
|
@ -278,7 +359,7 @@ def item_unique_field_values(key):
|
|||
|
||||
# Albums.
|
||||
|
||||
@app.route('/album/<idlist:ids>')
|
||||
@app.route('/album/<idlist:ids>', methods=["GET", "DELETE"])
|
||||
@resource('albums')
|
||||
def get_album(id):
|
||||
return g.lib.get_album(id)
|
||||
|
@ -291,7 +372,7 @@ def all_albums():
|
|||
return g.lib.albums()
|
||||
|
||||
|
||||
@app.route('/album/query/<query:queries>')
|
||||
@app.route('/album/query/<query:queries>', methods=["GET", "DELETE"])
|
||||
@resource_query('albums')
|
||||
def album_query(queries):
|
||||
return g.lib.albums(queries)
|
||||
|
@ -351,20 +432,21 @@ def home():
|
|||
|
||||
class WebPlugin(BeetsPlugin):
|
||||
def __init__(self):
|
||||
super(WebPlugin, self).__init__()
|
||||
super().__init__()
|
||||
self.config.add({
|
||||
'host': u'127.0.0.1',
|
||||
'host': '127.0.0.1',
|
||||
'port': 8337,
|
||||
'cors': '',
|
||||
'cors_supports_credentials': False,
|
||||
'reverse_proxy': False,
|
||||
'include_paths': False,
|
||||
'readonly': True,
|
||||
})
|
||||
|
||||
def commands(self):
|
||||
cmd = ui.Subcommand('web', help=u'start a Web interface')
|
||||
cmd.parser.add_option(u'-d', u'--debug', action='store_true',
|
||||
default=False, help=u'debug mode')
|
||||
cmd = ui.Subcommand('web', help='start a Web interface')
|
||||
cmd.parser.add_option('-d', '--debug', action='store_true',
|
||||
default=False, help='debug mode')
|
||||
|
||||
def func(lib, opts, args):
|
||||
args = ui.decargs(args)
|
||||
|
@ -378,12 +460,13 @@ class WebPlugin(BeetsPlugin):
|
|||
app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False
|
||||
|
||||
app.config['INCLUDE_PATHS'] = self.config['include_paths']
|
||||
app.config['READONLY'] = self.config['readonly']
|
||||
|
||||
# Enable CORS if required.
|
||||
if self.config['cors']:
|
||||
self._log.info(u'Enabling CORS with origin: {0}',
|
||||
self._log.info('Enabling CORS with origin: {0}',
|
||||
self.config['cors'])
|
||||
from flask.ext.cors import CORS
|
||||
from flask_cors import CORS
|
||||
app.config['CORS_ALLOW_HEADERS'] = "Content-Type"
|
||||
app.config['CORS_RESOURCES'] = {
|
||||
r"/*": {"origins": self.config['cors'].get(str)}
|
||||
|
@ -407,7 +490,7 @@ class WebPlugin(BeetsPlugin):
|
|||
return [cmd]
|
||||
|
||||
|
||||
class ReverseProxied(object):
|
||||
class ReverseProxied:
|
||||
'''Wrap the application in this middleware and configure the
|
||||
front-end server to add these headers, to let you quietly bind
|
||||
this to a URL other than / and to an HTTP scheme that is
|
||||
|
|
|
@ -129,7 +129,7 @@ $.fn.player = function(debug) {
|
|||
|
||||
// Simple selection disable for jQuery.
|
||||
// Cut-and-paste from:
|
||||
// http://stackoverflow.com/questions/2700000
|
||||
// https://stackoverflow.com/questions/2700000
|
||||
$.fn.disableSelection = function() {
|
||||
$(this).attr('unselectable', 'on')
|
||||
.css('-moz-user-select', 'none')
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue