mirror of
https://github.com/spl0k/supysonic.git
synced 2024-12-22 17:06:17 +00:00
Code style
This commit is contained in:
parent
c3f911b3f4
commit
799bfa3dde
@ -36,7 +36,7 @@ def api_routing(endpoint):
|
|||||||
@api.before_request
|
@api.before_request
|
||||||
def set_formatter():
|
def set_formatter():
|
||||||
"""Return a function to create the response."""
|
"""Return a function to create the response."""
|
||||||
f, callback = map(request.values.get, ["f", "callback"])
|
f, callback = map(request.values.get, ("f", "callback"))
|
||||||
if f == "jsonp":
|
if f == "jsonp":
|
||||||
request.formatter = JSONPFormatter(callback)
|
request.formatter = JSONPFormatter(callback)
|
||||||
elif f == "json":
|
elif f == "json":
|
||||||
|
@ -29,7 +29,7 @@ from .exceptions import GenericError, NotFound
|
|||||||
def rand_songs():
|
def rand_songs():
|
||||||
size = request.values.get("size", "10")
|
size = request.values.get("size", "10")
|
||||||
genre, fromYear, toYear, musicFolderId = map(
|
genre, fromYear, toYear, musicFolderId = map(
|
||||||
request.values.get, ["genre", "fromYear", "toYear", "musicFolderId"]
|
request.values.get, ("genre", "fromYear", "toYear", "musicFolderId")
|
||||||
)
|
)
|
||||||
|
|
||||||
size = int(size) if size else 10
|
size = int(size) if size else 10
|
||||||
@ -57,12 +57,12 @@ def rand_songs():
|
|||||||
|
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"randomSongs",
|
"randomSongs",
|
||||||
dict(
|
{
|
||||||
song=[
|
"song": [
|
||||||
t.as_subsonic_child(request.user, request.client)
|
t.as_subsonic_child(request.user, request.client)
|
||||||
for t in query.without_distinct().random(size)
|
for t in query.without_distinct().random(size)
|
||||||
]
|
]
|
||||||
),
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ def rand_songs():
|
|||||||
def album_list():
|
def album_list():
|
||||||
ltype = request.values["type"]
|
ltype = request.values["type"]
|
||||||
|
|
||||||
size, offset = map(request.values.get, ["size", "offset"])
|
size, offset = map(request.values.get, ("size", "offset"))
|
||||||
size = int(size) if size else 10
|
size = int(size) if size else 10
|
||||||
offset = int(offset) if offset else 0
|
offset = int(offset) if offset else 0
|
||||||
|
|
||||||
@ -78,12 +78,12 @@ def album_list():
|
|||||||
if ltype == "random":
|
if ltype == "random":
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"albumList",
|
"albumList",
|
||||||
dict(
|
{
|
||||||
album=[
|
"album": [
|
||||||
a.as_subsonic_child(request.user)
|
a.as_subsonic_child(request.user)
|
||||||
for a in distinct(query.random(size))
|
for a in distinct(query.random(size))
|
||||||
]
|
]
|
||||||
),
|
},
|
||||||
)
|
)
|
||||||
elif ltype == "newest":
|
elif ltype == "newest":
|
||||||
query = query.sort_by(desc(Folder.created)).distinct()
|
query = query.sort_by(desc(Folder.created)).distinct()
|
||||||
@ -123,9 +123,11 @@ def album_list():
|
|||||||
|
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"albumList",
|
"albumList",
|
||||||
dict(
|
{
|
||||||
album=[f.as_subsonic_child(request.user) for f in query.limit(size, offset)]
|
"album": [
|
||||||
),
|
f.as_subsonic_child(request.user) for f in query.limit(size, offset)
|
||||||
|
]
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -133,7 +135,7 @@ def album_list():
|
|||||||
def album_list_id3():
|
def album_list_id3():
|
||||||
ltype = request.values["type"]
|
ltype = request.values["type"]
|
||||||
|
|
||||||
size, offset = map(request.values.get, ["size", "offset"])
|
size, offset = map(request.values.get, ("size", "offset"))
|
||||||
size = int(size) if size else 10
|
size = int(size) if size else 10
|
||||||
offset = int(offset) if offset else 0
|
offset = int(offset) if offset else 0
|
||||||
|
|
||||||
@ -141,7 +143,7 @@ def album_list_id3():
|
|||||||
if ltype == "random":
|
if ltype == "random":
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"albumList2",
|
"albumList2",
|
||||||
dict(album=[a.as_subsonic_album(request.user) for a in query.random(size)]),
|
{"album": [a.as_subsonic_album(request.user) for a in query.random(size)]},
|
||||||
)
|
)
|
||||||
elif ltype == "newest":
|
elif ltype == "newest":
|
||||||
query = query.order_by(lambda a: desc(min(a.tracks.created)))
|
query = query.order_by(lambda a: desc(min(a.tracks.created)))
|
||||||
@ -177,9 +179,11 @@ def album_list_id3():
|
|||||||
|
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"albumList2",
|
"albumList2",
|
||||||
dict(
|
{
|
||||||
album=[f.as_subsonic_album(request.user) for f in query.limit(size, offset)]
|
"album": [
|
||||||
),
|
f.as_subsonic_album(request.user) for f in query.limit(size, offset)
|
||||||
|
]
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -187,14 +191,14 @@ def album_list_id3():
|
|||||||
def songs_by_genre():
|
def songs_by_genre():
|
||||||
genre = request.values["genre"]
|
genre = request.values["genre"]
|
||||||
|
|
||||||
count, offset = map(request.values.get, ["count", "offset"])
|
count, offset = map(request.values.get, ("count", "offset"))
|
||||||
count = int(count) if count else 10
|
count = int(count) if count else 10
|
||||||
offset = int(offset) if offset else 0
|
offset = int(offset) if offset else 0
|
||||||
|
|
||||||
query = select(t for t in Track if t.genre == genre).limit(count, offset)
|
query = select(t for t in Track if t.genre == genre).limit(count, offset)
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"songsByGenre",
|
"songsByGenre",
|
||||||
dict(song=[t.as_subsonic_child(request.user, request.client) for t in query]),
|
{"song": [t.as_subsonic_child(request.user, request.client) for t in query]},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -207,17 +211,17 @@ def now_playing():
|
|||||||
|
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"nowPlaying",
|
"nowPlaying",
|
||||||
dict(
|
{
|
||||||
entry=[
|
"entry": [
|
||||||
dict(
|
{
|
||||||
u.last_play.as_subsonic_child(request.user, request.client),
|
**u.last_play.as_subsonic_child(request.user, request.client),
|
||||||
username=u.name,
|
"username": u.name,
|
||||||
minutesAgo=(now() - u.last_play_date).seconds / 60,
|
"minutesAgo": (now() - u.last_play_date).seconds / 60,
|
||||||
playerId=0,
|
"playerId": 0,
|
||||||
)
|
}
|
||||||
for u in query
|
for u in query
|
||||||
]
|
]
|
||||||
),
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -227,22 +231,22 @@ def get_starred():
|
|||||||
|
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"starred",
|
"starred",
|
||||||
dict(
|
{
|
||||||
artist=[
|
"artist": [
|
||||||
sf.as_subsonic_artist(request.user)
|
sf.as_subsonic_artist(request.user)
|
||||||
for sf in folders.filter(lambda f: count(f.tracks) == 0)
|
for sf in folders.filter(lambda f: count(f.tracks) == 0)
|
||||||
],
|
],
|
||||||
album=[
|
"album": [
|
||||||
sf.as_subsonic_child(request.user)
|
sf.as_subsonic_child(request.user)
|
||||||
for sf in folders.filter(lambda f: count(f.tracks) > 0)
|
for sf in folders.filter(lambda f: count(f.tracks) > 0)
|
||||||
],
|
],
|
||||||
song=[
|
"song": [
|
||||||
st.as_subsonic_child(request.user, request.client)
|
st.as_subsonic_child(request.user, request.client)
|
||||||
for st in select(
|
for st in select(
|
||||||
s.starred for s in StarredTrack if s.user.id == request.user.id
|
s.starred for s in StarredTrack if s.user.id == request.user.id
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -250,24 +254,24 @@ def get_starred():
|
|||||||
def get_starred_id3():
|
def get_starred_id3():
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"starred2",
|
"starred2",
|
||||||
dict(
|
{
|
||||||
artist=[
|
"artist": [
|
||||||
sa.as_subsonic_artist(request.user)
|
sa.as_subsonic_artist(request.user)
|
||||||
for sa in select(
|
for sa in select(
|
||||||
s.starred for s in StarredArtist if s.user.id == request.user.id
|
s.starred for s in StarredArtist if s.user.id == request.user.id
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
album=[
|
"album": [
|
||||||
sa.as_subsonic_album(request.user)
|
sa.as_subsonic_album(request.user)
|
||||||
for sa in select(
|
for sa in select(
|
||||||
s.starred for s in StarredAlbum if s.user.id == request.user.id
|
s.starred for s in StarredAlbum if s.user.id == request.user.id
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
song=[
|
"song": [
|
||||||
st.as_subsonic_child(request.user, request.client)
|
st.as_subsonic_child(request.user, request.client)
|
||||||
for st in select(
|
for st in select(
|
||||||
s.starred for s in StarredTrack if s.user.id == request.user.id
|
s.starred for s in StarredTrack if s.user.id == request.user.id
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
},
|
||||||
)
|
)
|
||||||
|
@ -54,7 +54,7 @@ def unstar_single(cls, starcls, eid):
|
|||||||
|
|
||||||
|
|
||||||
def handle_star_request(func):
|
def handle_star_request(func):
|
||||||
id, albumId, artistId = map(request.values.getlist, ["id", "albumId", "artistId"])
|
id, albumId, artistId = map(request.values.getlist, ("id", "albumId", "artistId"))
|
||||||
|
|
||||||
if not id and not albumId and not artistId:
|
if not id and not albumId and not artistId:
|
||||||
raise MissingParameter("id, albumId or artistId")
|
raise MissingParameter("id, albumId or artistId")
|
||||||
@ -174,7 +174,7 @@ def rate():
|
|||||||
@api_routing("/scrobble")
|
@api_routing("/scrobble")
|
||||||
def scrobble():
|
def scrobble():
|
||||||
res = get_entity(Track)
|
res = get_entity(Track)
|
||||||
t, submission = map(request.values.get, ["time", "submission"])
|
t, submission = map(request.values.get, ("time", "submission"))
|
||||||
t = int(t) / 1000 if t else int(time.time())
|
t = int(t) / 1000 if t else int(time.time())
|
||||||
|
|
||||||
lfm = LastFm(current_app.config["LASTFM"], request.user)
|
lfm = LastFm(current_app.config["LASTFM"], request.user)
|
||||||
|
@ -20,12 +20,12 @@ from . import get_entity, get_entity_id, api_routing
|
|||||||
def list_folders():
|
def list_folders():
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"musicFolders",
|
"musicFolders",
|
||||||
dict(
|
{
|
||||||
musicFolder=[
|
"musicFolder": [
|
||||||
dict(id=str(f.id), name=f.name)
|
{"id": str(f.id), "name": f.name}
|
||||||
for f in Folder.select(lambda f: f.root).order_by(Folder.name)
|
for f in Folder.select(lambda f: f.root).order_by(Folder.name)
|
||||||
]
|
]
|
||||||
),
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -66,13 +66,14 @@ def list_indexes():
|
|||||||
|
|
||||||
folders = [folder]
|
folders = [folder]
|
||||||
|
|
||||||
last_modif = max(map(lambda f: f.last_scan, folders))
|
last_modif = max(f.last_scan for f in folders)
|
||||||
if ifModifiedSince is not None and last_modif < ifModifiedSince:
|
if ifModifiedSince is not None and last_modif < ifModifiedSince:
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"indexes",
|
"indexes",
|
||||||
dict(
|
{
|
||||||
lastModified=last_modif * 1000, ignoredArticles=ignored_articles_str()
|
"lastModified": last_modif * 1000,
|
||||||
),
|
"ignoredArticles": ignored_articles_str(),
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
# The XSD lies, we don't return artists but a directory structure
|
# The XSD lies, we don't return artists but a directory structure
|
||||||
@ -82,7 +83,7 @@ def list_indexes():
|
|||||||
artists += f.children.select()[:]
|
artists += f.children.select()[:]
|
||||||
children += f.tracks.select()[:]
|
children += f.tracks.select()[:]
|
||||||
|
|
||||||
indexes = dict()
|
indexes = {}
|
||||||
pattern = build_ignored_articles_pattern()
|
pattern = build_ignored_articles_pattern()
|
||||||
for artist in artists:
|
for artist in artists:
|
||||||
name = artist.name
|
name = artist.name
|
||||||
@ -101,24 +102,24 @@ def list_indexes():
|
|||||||
|
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"indexes",
|
"indexes",
|
||||||
dict(
|
{
|
||||||
lastModified=last_modif * 1000,
|
"lastModified": last_modif * 1000,
|
||||||
ignoredArticles=ignored_articles_str(),
|
"ignoredArticles": ignored_articles_str(),
|
||||||
index=[
|
"index": [
|
||||||
dict(
|
{
|
||||||
name=k,
|
"name": k,
|
||||||
artist=[
|
"artist": [
|
||||||
a.as_subsonic_artist(request.user)
|
a.as_subsonic_artist(request.user)
|
||||||
for a, _ in sorted(v, key=lambda t: t[1].lower())
|
for a, _ in sorted(v, key=lambda t: t[1].lower())
|
||||||
],
|
],
|
||||||
)
|
}
|
||||||
for k, v in sorted(indexes.items())
|
for k, v in sorted(indexes.items())
|
||||||
],
|
],
|
||||||
child=[
|
"child": [
|
||||||
c.as_subsonic_child(request.user, request.client)
|
c.as_subsonic_child(request.user, request.client)
|
||||||
for c in sorted(children, key=lambda t: t.sort_key())
|
for c in sorted(children, key=lambda t: t.sort_key())
|
||||||
],
|
],
|
||||||
),
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -134,21 +135,21 @@ def show_directory():
|
|||||||
def list_genres():
|
def list_genres():
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"genres",
|
"genres",
|
||||||
dict(
|
{
|
||||||
genre=[
|
"genre": [
|
||||||
dict(value=genre, songCount=sc, albumCount=ac)
|
{"value": genre, "songCount": sc, "albumCount": ac}
|
||||||
for genre, sc, ac in select(
|
for genre, sc, ac in select(
|
||||||
(t.genre, count(), count(t.album)) for t in Track if t.genre
|
(t.genre, count(), count(t.album)) for t in Track if t.genre
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
),
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@api_routing("/getArtists")
|
@api_routing("/getArtists")
|
||||||
def list_artists():
|
def list_artists():
|
||||||
# According to the API page, there are no parameters?
|
# According to the API page, there are no parameters?
|
||||||
indexes = dict()
|
indexes = {}
|
||||||
pattern = build_ignored_articles_pattern()
|
pattern = build_ignored_articles_pattern()
|
||||||
for artist in Artist.select():
|
for artist in Artist.select():
|
||||||
name = artist.name or "?"
|
name = artist.name or "?"
|
||||||
@ -167,19 +168,19 @@ def list_artists():
|
|||||||
|
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"artists",
|
"artists",
|
||||||
dict(
|
{
|
||||||
ignoredArticles=ignored_articles_str(),
|
"ignoredArticles": ignored_articles_str(),
|
||||||
index=[
|
"index": [
|
||||||
dict(
|
{
|
||||||
name=k,
|
"name": k,
|
||||||
artist=[
|
"artist": [
|
||||||
a.as_subsonic_artist(request.user)
|
a.as_subsonic_artist(request.user)
|
||||||
for a, _ in sorted(v, key=lambda t: t[1].lower())
|
for a, _ in sorted(v, key=lambda t: t[1].lower())
|
||||||
],
|
],
|
||||||
)
|
}
|
||||||
for k, v in sorted(indexes.items())
|
for k, v in sorted(indexes.items())
|
||||||
],
|
],
|
||||||
),
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ def get_chat():
|
|||||||
query = query.filter(lambda m: m.time > since)
|
query = query.filter(lambda m: m.time > since)
|
||||||
|
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"chatMessages", dict(chatMessage=[msg.responsize() for msg in query])
|
"chatMessages", {"chatMessage": [msg.responsize() for msg in query]}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -114,11 +114,12 @@ class AggregateException(SubsonicAPIException):
|
|||||||
|
|
||||||
codes = {exc.api_code for exc in self.exceptions}
|
codes = {exc.api_code for exc in self.exceptions}
|
||||||
errors = [
|
errors = [
|
||||||
dict(code=exc.api_code, message=exc.message) for exc in self.exceptions
|
{"code": exc.api_code, "message": exc.message} for exc in self.exceptions
|
||||||
]
|
]
|
||||||
|
|
||||||
rv = request.formatter(
|
rv = request.formatter(
|
||||||
"error", dict(code=list(codes)[0] if len(codes) == 1 else 0, error=errors)
|
"error",
|
||||||
|
{"code": next(iter(codes)) if len(codes) == 1 else 0, "error": errors},
|
||||||
)
|
)
|
||||||
# rv.status_code = self.code
|
# rv.status_code = self.code
|
||||||
return rv
|
return rv
|
||||||
|
@ -16,7 +16,7 @@ class BaseFormatter:
|
|||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def make_error(self, code, message):
|
def make_error(self, code, message):
|
||||||
return self.make_response("error", dict(code=code, message=message))
|
return self.make_response("error", {"code": code, "message": message})
|
||||||
|
|
||||||
def make_empty(self):
|
def make_empty(self):
|
||||||
return self.make_response(None, None)
|
return self.make_response(None, None)
|
||||||
@ -78,7 +78,7 @@ class JSONPFormatter(JSONBaseFormatter):
|
|||||||
def make_response(self, elem, data):
|
def make_response(self, elem, data):
|
||||||
if not self.__callback:
|
if not self.__callback:
|
||||||
return jsonify(
|
return jsonify(
|
||||||
self._subsonicify("error", dict(code=10, message="Missing callback"))
|
self._subsonicify("error", {"code": 10, "message": "Missing callback"})
|
||||||
)
|
)
|
||||||
|
|
||||||
rv = self._subsonicify(elem, data)
|
rv = self._subsonicify(elem, data)
|
||||||
@ -100,7 +100,7 @@ class XMLFormatter(BaseFormatter):
|
|||||||
"""
|
"""
|
||||||
if not isinstance(dictionary, dict):
|
if not isinstance(dictionary, dict):
|
||||||
raise TypeError("Expecting a dict")
|
raise TypeError("Expecting a dict")
|
||||||
if not all(map(lambda x: isinstance(x, str), dictionary)):
|
if not all(isinstance(x, str) for x in dictionary):
|
||||||
raise TypeError("Dictionary keys must be strings")
|
raise TypeError("Dictionary keys must be strings")
|
||||||
|
|
||||||
for name, value in dictionary.items():
|
for name, value in dictionary.items():
|
||||||
|
@ -79,12 +79,12 @@ def jukebox_control():
|
|||||||
except DaemonUnavailableError:
|
except DaemonUnavailableError:
|
||||||
raise GenericError("Jukebox unavaliable")
|
raise GenericError("Jukebox unavaliable")
|
||||||
|
|
||||||
rv = dict(
|
rv = {
|
||||||
currentIndex=status.index,
|
"currentIndex": status.index,
|
||||||
playing=status.playing,
|
"playing": status.playing,
|
||||||
gain=status.gain,
|
"gain": status.gain,
|
||||||
position=status.position,
|
"position": status.position,
|
||||||
)
|
}
|
||||||
if action == "get":
|
if action == "get":
|
||||||
playlist = []
|
playlist = []
|
||||||
for path in status.playlist:
|
for path in status.playlist:
|
||||||
|
@ -73,7 +73,7 @@ def stream_media():
|
|||||||
raise UnsupportedParameter("size")
|
raise UnsupportedParameter("size")
|
||||||
|
|
||||||
maxBitRate, request_format, estimateContentLength = map(
|
maxBitRate, request_format, estimateContentLength = map(
|
||||||
request.values.get, ["maxBitRate", "format", "estimateContentLength"]
|
request.values.get, ("maxBitRate", "format", "estimateContentLength")
|
||||||
)
|
)
|
||||||
if request_format:
|
if request_format:
|
||||||
request_format = request_format.lower()
|
request_format = request_format.lower()
|
||||||
@ -378,7 +378,7 @@ def cover_art():
|
|||||||
def lyrics_response_for_track(track, lyrics):
|
def lyrics_response_for_track(track, lyrics):
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"lyrics",
|
"lyrics",
|
||||||
dict(artist=track.album.artist.name, title=track.title, value=lyrics),
|
{"artist": track.album.artist.name, "title": track.title, "value": lyrics},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -419,7 +419,7 @@ def lyrics():
|
|||||||
).hexdigest()
|
).hexdigest()
|
||||||
cache_key = "lyrics-{}".format(unique)
|
cache_key = "lyrics-{}".format(unique)
|
||||||
|
|
||||||
lyrics = dict()
|
lyrics = {}
|
||||||
try:
|
try:
|
||||||
lyrics = json.loads(
|
lyrics = json.loads(
|
||||||
zlib.decompress(current_app.cache.get_value(cache_key)).decode("utf-8")
|
zlib.decompress(current_app.cache.get_value(cache_key)).decode("utf-8")
|
||||||
@ -434,11 +434,11 @@ def lyrics():
|
|||||||
root = ElementTree.fromstring(r.content)
|
root = ElementTree.fromstring(r.content)
|
||||||
|
|
||||||
ns = {"cl": "http://api.chartlyrics.com/"}
|
ns = {"cl": "http://api.chartlyrics.com/"}
|
||||||
lyrics = dict(
|
lyrics = {
|
||||||
artist=root.find("cl:LyricArtist", namespaces=ns).text,
|
"artist": root.find("cl:LyricArtist", namespaces=ns).text,
|
||||||
title=root.find("cl:LyricSong", namespaces=ns).text,
|
"title": root.find("cl:LyricSong", namespaces=ns).text,
|
||||||
value=root.find("cl:Lyric", namespaces=ns).text,
|
"value": root.find("cl:Lyric", namespaces=ns).text,
|
||||||
)
|
}
|
||||||
|
|
||||||
current_app.cache.set(
|
current_app.cache.set(
|
||||||
cache_key, zlib.compress(json.dumps(lyrics).encode("utf-8"), 9)
|
cache_key, zlib.compress(json.dumps(lyrics).encode("utf-8"), 9)
|
||||||
|
@ -36,7 +36,7 @@ def list_playlists():
|
|||||||
|
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"playlists",
|
"playlists",
|
||||||
dict(playlist=[p.as_subsonic_playlist(request.user) for p in query]),
|
{"playlist": [p.as_subsonic_playlist(request.user) for p in query]},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ def show_playlist():
|
|||||||
|
|
||||||
@api_routing("/createPlaylist")
|
@api_routing("/createPlaylist")
|
||||||
def create_playlist():
|
def create_playlist():
|
||||||
playlist_id, name = map(request.values.get, ["playlistId", "name"])
|
playlist_id, name = map(request.values.get, ("playlistId", "name"))
|
||||||
# songId actually doesn't seem to be required
|
# songId actually doesn't seem to be required
|
||||||
songs = request.values.getlist("songId")
|
songs = request.values.getlist("songId")
|
||||||
playlist_id = uuid.UUID(playlist_id) if playlist_id else None
|
playlist_id = uuid.UUID(playlist_id) if playlist_id else None
|
||||||
@ -99,9 +99,9 @@ def update_playlist():
|
|||||||
raise Forbidden()
|
raise Forbidden()
|
||||||
|
|
||||||
playlist = res
|
playlist = res
|
||||||
name, comment, public = map(request.values.get, ["name", "comment", "public"])
|
name, comment, public = map(request.values.get, ("name", "comment", "public"))
|
||||||
to_add, to_remove = map(
|
to_add, to_remove = map(
|
||||||
request.values.getlist, ["songIdToAdd", "songIndexToRemove"]
|
request.values.getlist, ("songIdToAdd", "songIndexToRemove")
|
||||||
)
|
)
|
||||||
|
|
||||||
if name:
|
if name:
|
||||||
|
@ -18,7 +18,7 @@ def get_radio_stations():
|
|||||||
query = RadioStation.select().sort_by(RadioStation.name)
|
query = RadioStation.select().sort_by(RadioStation.name)
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"internetRadioStations",
|
"internetRadioStations",
|
||||||
dict(internetRadioStation=[p.as_subsonic_station() for p in query]),
|
{"internetRadioStation": [p.as_subsonic_station() for p in query]},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ def create_radio_station():
|
|||||||
raise Forbidden()
|
raise Forbidden()
|
||||||
|
|
||||||
stream_url, name, homepage_url = map(
|
stream_url, name, homepage_url = map(
|
||||||
request.values.get, ["streamUrl", "name", "homepageUrl"]
|
request.values.get, ("streamUrl", "name", "homepageUrl")
|
||||||
)
|
)
|
||||||
|
|
||||||
if stream_url and name:
|
if stream_url and name:
|
||||||
@ -47,7 +47,7 @@ def update_radio_station():
|
|||||||
res = get_entity(RadioStation)
|
res = get_entity(RadioStation)
|
||||||
|
|
||||||
stream_url, name, homepage_url = map(
|
stream_url, name, homepage_url = map(
|
||||||
request.values.get, ["streamUrl", "name", "homepageUrl"]
|
request.values.get, ("streamUrl", "name", "homepageUrl")
|
||||||
)
|
)
|
||||||
if stream_url and name:
|
if stream_url and name:
|
||||||
res.stream_url = stream_url
|
res.stream_url = stream_url
|
||||||
|
@ -28,10 +28,10 @@ def startScan():
|
|||||||
raise ServerError(str(e))
|
raise ServerError(str(e))
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"scanStatus",
|
"scanStatus",
|
||||||
dict(
|
{
|
||||||
scanning="true" if scanned is not None else "false",
|
"scanning": scanned is not None,
|
||||||
count=scanned if scanned is not None else 0,
|
"count": scanned or 0,
|
||||||
),
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -46,8 +46,8 @@ def getScanStatus():
|
|||||||
raise ServerError(str(e))
|
raise ServerError(str(e))
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"scanStatus",
|
"scanStatus",
|
||||||
dict(
|
{
|
||||||
scanning="true" if scanned is not None else "false",
|
"scanning": scanned is not None,
|
||||||
count=scanned if scanned is not None else 0,
|
"count": scanned or 0,
|
||||||
),
|
},
|
||||||
)
|
)
|
||||||
|
@ -20,7 +20,7 @@ from .exceptions import MissingParameter
|
|||||||
def old_search():
|
def old_search():
|
||||||
artist, album, title, anyf, count, offset, newer_than = map(
|
artist, album, title, anyf, count, offset, newer_than = map(
|
||||||
request.values.get,
|
request.values.get,
|
||||||
["artist", "album", "title", "any", "count", "offset", "newerThan"],
|
("artist", "album", "title", "any", "count", "offset", "newerThan"),
|
||||||
)
|
)
|
||||||
|
|
||||||
count = int(count) if count else 20
|
count = int(count) if count else 20
|
||||||
@ -54,32 +54,32 @@ def old_search():
|
|||||||
|
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"searchResult",
|
"searchResult",
|
||||||
dict(
|
{
|
||||||
totalHits=folders.count() + tracks.count(),
|
"totalHits": folders.count() + tracks.count(),
|
||||||
offset=offset,
|
"offset": offset,
|
||||||
match=[
|
"match": [
|
||||||
r.as_subsonic_child(request.user)
|
r.as_subsonic_child(request.user)
|
||||||
if isinstance(r, Folder)
|
if isinstance(r, Folder)
|
||||||
else r.as_subsonic_child(request.user, request.client)
|
else r.as_subsonic_child(request.user, request.client)
|
||||||
for r in res
|
for r in res
|
||||||
],
|
],
|
||||||
),
|
},
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise MissingParameter("search")
|
raise MissingParameter("search")
|
||||||
|
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"searchResult",
|
"searchResult",
|
||||||
dict(
|
{
|
||||||
totalHits=query.count(),
|
"totalHits": query.count(),
|
||||||
offset=offset,
|
"offset": offset,
|
||||||
match=[
|
"match": [
|
||||||
r.as_subsonic_child(request.user)
|
r.as_subsonic_child(request.user)
|
||||||
if isinstance(r, Folder)
|
if isinstance(r, Folder)
|
||||||
else r.as_subsonic_child(request.user, request.client)
|
else r.as_subsonic_child(request.user, request.client)
|
||||||
for r in query[offset : offset + count]
|
for r in query[offset : offset + count]
|
||||||
],
|
],
|
||||||
),
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -95,14 +95,14 @@ def new_search():
|
|||||||
song_offset,
|
song_offset,
|
||||||
) = map(
|
) = map(
|
||||||
request.values.get,
|
request.values.get,
|
||||||
[
|
(
|
||||||
"artistCount",
|
"artistCount",
|
||||||
"artistOffset",
|
"artistOffset",
|
||||||
"albumCount",
|
"albumCount",
|
||||||
"albumOffset",
|
"albumOffset",
|
||||||
"songCount",
|
"songCount",
|
||||||
"songOffset",
|
"songOffset",
|
||||||
],
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
artist_count = int(artist_count) if artist_count else 20
|
artist_count = int(artist_count) if artist_count else 20
|
||||||
@ -147,14 +147,14 @@ def search_id3():
|
|||||||
song_offset,
|
song_offset,
|
||||||
) = map(
|
) = map(
|
||||||
request.values.get,
|
request.values.get,
|
||||||
[
|
(
|
||||||
"artistCount",
|
"artistCount",
|
||||||
"artistOffset",
|
"artistOffset",
|
||||||
"albumCount",
|
"albumCount",
|
||||||
"albumOffset",
|
"albumOffset",
|
||||||
"songCount",
|
"songCount",
|
||||||
"songOffset",
|
"songOffset",
|
||||||
],
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
artist_count = int(artist_count) if artist_count else 20
|
artist_count = int(artist_count) if artist_count else 20
|
||||||
|
@ -18,4 +18,4 @@ def ping():
|
|||||||
|
|
||||||
@api_routing("/getLicense")
|
@api_routing("/getLicense")
|
||||||
def license():
|
def license():
|
||||||
return request.formatter("license", dict(valid=True))
|
return request.formatter("license", {"valid": True})
|
||||||
|
@ -43,7 +43,7 @@ def user_info():
|
|||||||
@admin_only
|
@admin_only
|
||||||
def users_info():
|
def users_info():
|
||||||
return request.formatter(
|
return request.formatter(
|
||||||
"users", dict(user=[u.as_subsonic_user() for u in User.select()])
|
"users", {"user": [u.as_subsonic_user() for u in User.select()]}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ def user_edit():
|
|||||||
UserManager.change_password2(user, password)
|
UserManager.change_password2(user, password)
|
||||||
|
|
||||||
email, admin, jukebox = map(
|
email, admin, jukebox = map(
|
||||||
request.values.get, ["email", "adminRole", "jukeboxRole"]
|
request.values.get, ("email", "adminRole", "jukeboxRole")
|
||||||
)
|
)
|
||||||
if email is not None:
|
if email is not None:
|
||||||
user.mail = email
|
user.mail = email
|
||||||
|
220
supysonic/db.py
220
supysonic/db.py
@ -92,13 +92,13 @@ class Folder(PathMixin, db.Entity):
|
|||||||
ratings = Set(lambda: RatingFolder)
|
ratings = Set(lambda: RatingFolder)
|
||||||
|
|
||||||
def as_subsonic_child(self, user):
|
def as_subsonic_child(self, user):
|
||||||
info = dict(
|
info = {
|
||||||
id=str(self.id),
|
"id": str(self.id),
|
||||||
isDir=True,
|
"isDir": True,
|
||||||
title=self.name,
|
"title": self.name,
|
||||||
album=self.name,
|
"album": self.name,
|
||||||
created=self.created.isoformat(),
|
"created": self.created.isoformat(),
|
||||||
)
|
}
|
||||||
if not self.root:
|
if not self.root:
|
||||||
info["parent"] = str(self.parent.id)
|
info["parent"] = str(self.parent.id)
|
||||||
info["artist"] = self.parent.name
|
info["artist"] = self.parent.name
|
||||||
@ -129,7 +129,7 @@ class Folder(PathMixin, db.Entity):
|
|||||||
return info
|
return info
|
||||||
|
|
||||||
def as_subsonic_artist(self, user): # "Artist" type in XSD
|
def as_subsonic_artist(self, user): # "Artist" type in XSD
|
||||||
info = dict(id=str(self.id), name=self.name)
|
info = {"id": str(self.id), "name": self.name}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
starred = StarredFolder[user.id, self.id]
|
starred = StarredFolder[user.id, self.id]
|
||||||
@ -140,10 +140,10 @@ class Folder(PathMixin, db.Entity):
|
|||||||
return info
|
return info
|
||||||
|
|
||||||
def as_subsonic_directory(self, user, client): # "Directory" type in XSD
|
def as_subsonic_directory(self, user, client): # "Directory" type in XSD
|
||||||
info = dict(
|
info = {
|
||||||
id=str(self.id),
|
"id": str(self.id),
|
||||||
name=self.name,
|
"name": self.name,
|
||||||
child=[
|
"child": [
|
||||||
f.as_subsonic_child(user)
|
f.as_subsonic_child(user)
|
||||||
for f in self.children.order_by(lambda c: c.name.lower())
|
for f in self.children.order_by(lambda c: c.name.lower())
|
||||||
]
|
]
|
||||||
@ -151,7 +151,7 @@ class Folder(PathMixin, db.Entity):
|
|||||||
t.as_subsonic_child(user, client)
|
t.as_subsonic_child(user, client)
|
||||||
for t in sorted(self.tracks, key=lambda t: t.sort_key())
|
for t in sorted(self.tracks, key=lambda t: t.sort_key())
|
||||||
],
|
],
|
||||||
)
|
}
|
||||||
if not self.root:
|
if not self.root:
|
||||||
info["parent"] = str(self.parent.id)
|
info["parent"] = str(self.parent.id)
|
||||||
|
|
||||||
@ -183,12 +183,12 @@ class Artist(db.Entity):
|
|||||||
stars = Set(lambda: StarredArtist)
|
stars = Set(lambda: StarredArtist)
|
||||||
|
|
||||||
def as_subsonic_artist(self, user):
|
def as_subsonic_artist(self, user):
|
||||||
info = dict(
|
info = {
|
||||||
id=str(self.id),
|
"id": str(self.id),
|
||||||
name=self.name,
|
"name": self.name,
|
||||||
# coverArt
|
# coverArt
|
||||||
albumCount=self.albums.count(),
|
"albumCount": self.albums.count(),
|
||||||
)
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
starred = StarredArtist[user.id, self.id]
|
starred = StarredArtist[user.id, self.id]
|
||||||
@ -217,15 +217,15 @@ class Album(db.Entity):
|
|||||||
stars = Set(lambda: StarredAlbum)
|
stars = Set(lambda: StarredAlbum)
|
||||||
|
|
||||||
def as_subsonic_album(self, user): # "AlbumID3" type in XSD
|
def as_subsonic_album(self, user): # "AlbumID3" type in XSD
|
||||||
info = dict(
|
info = {
|
||||||
id=str(self.id),
|
"id": str(self.id),
|
||||||
name=self.name,
|
"name": self.name,
|
||||||
artist=self.artist.name,
|
"artist": self.artist.name,
|
||||||
artistId=str(self.artist.id),
|
"artistId": str(self.artist.id),
|
||||||
songCount=self.tracks.count(),
|
"songCount": self.tracks.count(),
|
||||||
duration=sum(self.tracks.duration),
|
"duration": sum(self.tracks.duration),
|
||||||
created=min(self.tracks.created).isoformat(),
|
"created": min(self.tracks.created).isoformat(),
|
||||||
)
|
}
|
||||||
|
|
||||||
track_with_cover = self.tracks.select(
|
track_with_cover = self.tracks.select(
|
||||||
lambda t: t.folder.cover_art is not None
|
lambda t: t.folder.cover_art is not None
|
||||||
@ -253,8 +253,8 @@ class Album(db.Entity):
|
|||||||
return info
|
return info
|
||||||
|
|
||||||
def sort_key(self):
|
def sort_key(self):
|
||||||
year = min(map(lambda t: t.year if t.year else 9999, self.tracks))
|
year = min(t.year if t.year else 9999 for t in self.tracks)
|
||||||
return "%i%s" % (year, self.name.lower())
|
return f"{year}{self.name.lower()}"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def prune(cls):
|
def prune(cls):
|
||||||
@ -297,27 +297,27 @@ class Track(PathMixin, db.Entity):
|
|||||||
ratings = Set(lambda: RatingTrack)
|
ratings = Set(lambda: RatingTrack)
|
||||||
|
|
||||||
def as_subsonic_child(self, user, prefs):
|
def as_subsonic_child(self, user, prefs):
|
||||||
info = dict(
|
info = {
|
||||||
id=str(self.id),
|
"id": str(self.id),
|
||||||
parent=str(self.folder.id),
|
"parent": str(self.folder.id),
|
||||||
isDir=False,
|
"isDir": False,
|
||||||
title=self.title,
|
"title": self.title,
|
||||||
album=self.album.name,
|
"album": self.album.name,
|
||||||
artist=self.artist.name,
|
"artist": self.artist.name,
|
||||||
track=self.number,
|
"track": self.number,
|
||||||
size=os.path.getsize(self.path) if os.path.isfile(self.path) else -1,
|
"size": os.path.getsize(self.path) if os.path.isfile(self.path) else -1,
|
||||||
contentType=self.mimetype,
|
"contentType": self.mimetype,
|
||||||
suffix=self.suffix(),
|
"suffix": self.suffix(),
|
||||||
duration=self.duration,
|
"duration": self.duration,
|
||||||
bitRate=self.bitrate,
|
"bitRate": self.bitrate,
|
||||||
path=self.path[len(self.root_folder.path) + 1 :],
|
"path": self.path[len(self.root_folder.path) + 1 :],
|
||||||
isVideo=False,
|
"isVideo": False,
|
||||||
discNumber=self.disc,
|
"discNumber": self.disc,
|
||||||
created=self.created.isoformat(),
|
"created": self.created.isoformat(),
|
||||||
albumId=str(self.album.id),
|
"albumId": str(self.album.id),
|
||||||
artistId=str(self.artist.id),
|
"artistId": str(self.artist.id),
|
||||||
type="music",
|
"type": "music",
|
||||||
)
|
}
|
||||||
|
|
||||||
if self.year:
|
if self.year:
|
||||||
info["year"] = self.year
|
info["year"] = self.year
|
||||||
@ -362,22 +362,16 @@ class Track(PathMixin, db.Entity):
|
|||||||
return mimetypes.guess_type(self.path, False)[0] or "application/octet-stream"
|
return mimetypes.guess_type(self.path, False)[0] or "application/octet-stream"
|
||||||
|
|
||||||
def duration_str(self):
|
def duration_str(self):
|
||||||
ret = "%02i:%02i" % ((self.duration % 3600) / 60, self.duration % 60)
|
ret = "{:02}:{:02}".format((self.duration % 3600) / 60, self.duration % 60)
|
||||||
if self.duration >= 3600:
|
if self.duration >= 3600:
|
||||||
ret = "%02i:%s" % (self.duration / 3600, ret)
|
ret = "{:02}:{}".format(self.duration / 3600, ret)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def suffix(self):
|
def suffix(self):
|
||||||
return os.path.splitext(self.path)[1][1:].lower()
|
return os.path.splitext(self.path)[1][1:].lower()
|
||||||
|
|
||||||
def sort_key(self):
|
def sort_key(self):
|
||||||
return (
|
return f"{self.album.artist.name}{self.album.name}{self.disc:02}{self.number:02}{self.title}".lower()
|
||||||
self.album.artist.name
|
|
||||||
+ self.album.name
|
|
||||||
+ ("%02i" % self.disc)
|
|
||||||
+ ("%02i" % self.number)
|
|
||||||
+ self.title
|
|
||||||
).lower()
|
|
||||||
|
|
||||||
|
|
||||||
class User(db.Entity):
|
class User(db.Entity):
|
||||||
@ -412,22 +406,22 @@ class User(db.Entity):
|
|||||||
track_ratings = Set(lambda: RatingTrack, lazy=True)
|
track_ratings = Set(lambda: RatingTrack, lazy=True)
|
||||||
|
|
||||||
def as_subsonic_user(self):
|
def as_subsonic_user(self):
|
||||||
return dict(
|
return {
|
||||||
username=self.name,
|
"username": self.name,
|
||||||
email=self.mail,
|
"email": self.mail,
|
||||||
scrobblingEnabled=self.lastfm_session is not None and self.lastfm_status,
|
"scrobblingEnabled": self.lastfm_session is not None and self.lastfm_status,
|
||||||
adminRole=self.admin,
|
"adminRole": self.admin,
|
||||||
settingsRole=True,
|
"settingsRole": True,
|
||||||
downloadRole=True,
|
"downloadRole": True,
|
||||||
uploadRole=False,
|
"uploadRole": False,
|
||||||
playlistRole=True,
|
"playlistRole": True,
|
||||||
coverArtRole=False,
|
"coverArtRole": False,
|
||||||
commentRole=False,
|
"commentRole": False,
|
||||||
podcastRole=False,
|
"podcastRole": False,
|
||||||
streamRole=True,
|
"streamRole": True,
|
||||||
jukeboxRole=self.admin or self.jukebox,
|
"jukeboxRole": self.admin or self.jukebox,
|
||||||
shareRole=False,
|
"shareRole": False,
|
||||||
)
|
}
|
||||||
|
|
||||||
|
|
||||||
class ClientPrefs(db.Entity):
|
class ClientPrefs(db.Entity):
|
||||||
@ -507,9 +501,11 @@ class ChatMessage(db.Entity):
|
|||||||
message = Required(str, 512)
|
message = Required(str, 512)
|
||||||
|
|
||||||
def responsize(self):
|
def responsize(self):
|
||||||
return dict(
|
return {
|
||||||
username=self.user.name, time=self.time * 1000, message=self.message
|
"username": self.user.name,
|
||||||
)
|
"time": self.time * 1000,
|
||||||
|
"message": self.message,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Playlist(db.Entity):
|
class Playlist(db.Entity):
|
||||||
@ -525,17 +521,17 @@ class Playlist(db.Entity):
|
|||||||
|
|
||||||
def as_subsonic_playlist(self, user):
|
def as_subsonic_playlist(self, user):
|
||||||
tracks = self.get_tracks()
|
tracks = self.get_tracks()
|
||||||
info = dict(
|
info = {
|
||||||
id=str(self.id),
|
"id": str(self.id),
|
||||||
name=self.name
|
"name": self.name
|
||||||
if self.user.id == user.id
|
if self.user.id == user.id
|
||||||
else "[{}] {}".format(self.user.name, self.name),
|
else "[{}] {}".format(self.user.name, self.name),
|
||||||
owner=self.user.name,
|
"owner": self.user.name,
|
||||||
public=self.public,
|
"public": self.public,
|
||||||
songCount=len(tracks),
|
"songCount": len(tracks),
|
||||||
duration=sum(map(lambda t: t.duration, tracks)),
|
"duration": sum(t.duration for t in tracks),
|
||||||
created=self.created.isoformat(),
|
"created": self.created.isoformat(),
|
||||||
)
|
}
|
||||||
if self.comment:
|
if self.comment:
|
||||||
info["comment"] = self.comment
|
info["comment"] = self.comment
|
||||||
return info
|
return info
|
||||||
@ -556,7 +552,7 @@ class Playlist(db.Entity):
|
|||||||
should_fix = True
|
should_fix = True
|
||||||
|
|
||||||
if should_fix:
|
if should_fix:
|
||||||
self.tracks = ",".join(map(lambda t: str(t.id), tracks))
|
self.tracks = ",".join(str(t.id) for t in tracks)
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
return tracks
|
return tracks
|
||||||
@ -597,12 +593,12 @@ class RadioStation(db.Entity):
|
|||||||
created = Required(datetime, precision=0, default=now)
|
created = Required(datetime, precision=0, default=now)
|
||||||
|
|
||||||
def as_subsonic_station(self):
|
def as_subsonic_station(self):
|
||||||
info = dict(
|
info = {
|
||||||
id=str(self.id),
|
"id": str(self.id),
|
||||||
streamUrl=self.stream_url,
|
"streamUrl": self.stream_url,
|
||||||
name=self.name,
|
"name": self.name,
|
||||||
homePageUrl=self.homepage_url,
|
"homePageUrl": self.homepage_url,
|
||||||
)
|
}
|
||||||
return info
|
return info
|
||||||
|
|
||||||
|
|
||||||
@ -622,28 +618,28 @@ def parse_uri(database_uri):
|
|||||||
elif path[0] == "/":
|
elif path[0] == "/":
|
||||||
path = path[1:]
|
path = path[1:]
|
||||||
|
|
||||||
return dict(provider="sqlite", filename=path, create_db=True, **args)
|
return {"provider": "sqlite", "filename": path, "create_db": True, **args}
|
||||||
elif uri.scheme in ("postgres", "postgresql"):
|
elif uri.scheme in ("postgres", "postgresql"):
|
||||||
return dict(
|
return {
|
||||||
provider="postgres",
|
"provider": "postgres",
|
||||||
user=uri.username,
|
"user": uri.username,
|
||||||
password=uri.password,
|
"password": uri.password,
|
||||||
host=uri.hostname,
|
"host": uri.hostname,
|
||||||
dbname=uri.path[1:],
|
"dbname": uri.path[1:],
|
||||||
**args
|
**args,
|
||||||
)
|
}
|
||||||
elif uri.scheme == "mysql":
|
elif uri.scheme == "mysql":
|
||||||
args.setdefault("charset", "utf8mb4")
|
args.setdefault("charset", "utf8mb4")
|
||||||
args.setdefault("binary_prefix", True)
|
args.setdefault("binary_prefix", True)
|
||||||
return dict(
|
return {
|
||||||
provider="mysql",
|
"provider": "mysql",
|
||||||
user=uri.username,
|
"user": uri.username,
|
||||||
passwd=uri.password,
|
"passwd": uri.password,
|
||||||
host=uri.hostname,
|
"host": uri.hostname,
|
||||||
db=uri.path[1:],
|
"db": uri.path[1:],
|
||||||
**args
|
**args,
|
||||||
)
|
}
|
||||||
return dict()
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def execute_sql_resource_script(respath):
|
def execute_sql_resource_script(respath):
|
||||||
|
@ -43,7 +43,7 @@ def add_folder_form():
|
|||||||
@admin_only
|
@admin_only
|
||||||
def add_folder_post():
|
def add_folder_post():
|
||||||
error = False
|
error = False
|
||||||
(name, path) = map(request.form.get, ["name", "path"])
|
name, path = map(request.form.get, ("name", "path"))
|
||||||
if name in (None, ""):
|
if name in (None, ""):
|
||||||
flash("The name is required.")
|
flash("The name is required.")
|
||||||
error = True
|
error = True
|
||||||
@ -59,7 +59,7 @@ def add_folder_post():
|
|||||||
flash(str(e), "error")
|
flash(str(e), "error")
|
||||||
return render_template("addfolder.html")
|
return render_template("addfolder.html")
|
||||||
|
|
||||||
flash("Folder '%s' created. You should now run a scan" % name)
|
flash(f"Folder '{name}' created. You should now run a scan")
|
||||||
return redirect(url_for("frontend.folder_index"))
|
return redirect(url_for("frontend.folder_index"))
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ def user_profile(uid, user):
|
|||||||
@frontend.route("/user/<uid>", methods=["POST"])
|
@frontend.route("/user/<uid>", methods=["POST"])
|
||||||
@me_or_uuid
|
@me_or_uuid
|
||||||
def update_clients(uid, user):
|
def update_clients(uid, user):
|
||||||
clients_opts = dict()
|
clients_opts = {}
|
||||||
for key, value in request.form.items():
|
for key, value in request.form.items():
|
||||||
if "_" not in key:
|
if "_" not in key:
|
||||||
continue
|
continue
|
||||||
@ -85,7 +85,7 @@ def update_clients(uid, user):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if client not in clients_opts:
|
if client not in clients_opts:
|
||||||
clients_opts[client] = dict([(opt, value)])
|
clients_opts[client] = {opt: value}
|
||||||
else:
|
else:
|
||||||
clients_opts[client][opt] = value
|
clients_opts[client][opt] = value
|
||||||
logger.debug(clients_opts)
|
logger.debug(clients_opts)
|
||||||
@ -157,9 +157,9 @@ def change_username_post(uid):
|
|||||||
if user.name != username or user.admin != admin:
|
if user.name != username or user.admin != admin:
|
||||||
user.name = username
|
user.name = username
|
||||||
user.admin = admin
|
user.admin = admin
|
||||||
flash("User '%s' updated." % username)
|
flash(f"User '{username}' updated.")
|
||||||
else:
|
else:
|
||||||
flash("No changes for '%s'." % username)
|
flash(f"No changes for '{username}'.")
|
||||||
|
|
||||||
return redirect(url_for("frontend.user_profile", uid=uid))
|
return redirect(url_for("frontend.user_profile", uid=uid))
|
||||||
|
|
||||||
@ -195,7 +195,7 @@ def change_password_post(uid, user):
|
|||||||
flash("The current password is required")
|
flash("The current password is required")
|
||||||
error = True
|
error = True
|
||||||
|
|
||||||
new, confirm = map(request.form.get, ["new", "confirm"])
|
new, confirm = map(request.form.get, ("new", "confirm"))
|
||||||
|
|
||||||
if not new:
|
if not new:
|
||||||
flash("The new password is required")
|
flash("The new password is required")
|
||||||
@ -231,7 +231,7 @@ def add_user_post():
|
|||||||
error = False
|
error = False
|
||||||
args = request.form.copy()
|
args = request.form.copy()
|
||||||
(name, passwd, passwd_confirm) = map(
|
(name, passwd, passwd_confirm) = map(
|
||||||
args.pop, ["user", "passwd", "passwd_confirm"], [None] * 3
|
args.pop, ("user", "passwd", "passwd_confirm"), (None,) * 3
|
||||||
)
|
)
|
||||||
if not name:
|
if not name:
|
||||||
flash("The name is required.")
|
flash("The name is required.")
|
||||||
@ -246,7 +246,7 @@ def add_user_post():
|
|||||||
if not error:
|
if not error:
|
||||||
try:
|
try:
|
||||||
UserManager.add(name, passwd, **args)
|
UserManager.add(name, passwd, **args)
|
||||||
flash("User '%s' successfully added" % name)
|
flash(f"User '{name}' successfully added")
|
||||||
return redirect(url_for("frontend.user_index"))
|
return redirect(url_for("frontend.user_index"))
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
flash(str(e), "error")
|
flash(str(e), "error")
|
||||||
@ -302,7 +302,7 @@ def login():
|
|||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
return render_template("login.html")
|
return render_template("login.html")
|
||||||
|
|
||||||
name, password = map(request.form.get, ["user", "password"])
|
name, password = map(request.form.get, ("user", "password"))
|
||||||
error = False
|
error = False
|
||||||
if not name:
|
if not name:
|
||||||
flash("Missing user name")
|
flash("Missing user name")
|
||||||
|
@ -30,7 +30,7 @@ class LastFm:
|
|||||||
if not res:
|
if not res:
|
||||||
return False, "Error connecting to LastFM"
|
return False, "Error connecting to LastFM"
|
||||||
elif "error" in res:
|
elif "error" in res:
|
||||||
return False, "Error %i: %s" % (res["error"], res["message"])
|
return False, f"Error {res['error']}: {res['message']}"
|
||||||
else:
|
else:
|
||||||
self.__user.lastfm_session = res["session"]["key"]
|
self.__user.lastfm_session = res["session"]["key"]
|
||||||
self.__user.lastfm_status = True
|
self.__user.lastfm_status = True
|
||||||
@ -107,6 +107,6 @@ class LastFm:
|
|||||||
if "error" in json:
|
if "error" in json:
|
||||||
if json["error"] in (9, "9"):
|
if json["error"] in (9, "9"):
|
||||||
self.__user.lastfm_status = False
|
self.__user.lastfm_status = False
|
||||||
logger.warning("LastFM error %i: %s" % (json["error"], json["message"]))
|
logger.warning("LastFM error %i: %s", json["error"], json["message"])
|
||||||
|
|
||||||
return json
|
return json
|
||||||
|
@ -400,9 +400,12 @@ class Scanner(Thread):
|
|||||||
|
|
||||||
created = datetime.fromtimestamp(os.path.getmtime(path))
|
created = datetime.fromtimestamp(os.path.getmtime(path))
|
||||||
children.append(
|
children.append(
|
||||||
dict(
|
{
|
||||||
root=False, name=os.path.basename(path), path=path, created=created
|
"root": False,
|
||||||
)
|
"name": os.path.basename(path),
|
||||||
|
"path": path,
|
||||||
|
"created": created,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
path = os.path.dirname(path)
|
path = os.path.dirname(path)
|
||||||
|
|
||||||
|
@ -31,9 +31,9 @@ class SupysonicWatcherEventHandler(PatternMatchingEventHandler):
|
|||||||
def __init__(self, extensions):
|
def __init__(self, extensions):
|
||||||
patterns = None
|
patterns = None
|
||||||
if extensions:
|
if extensions:
|
||||||
patterns = list(map(lambda e: "*." + e.lower(), extensions.split())) + list(
|
patterns = ["*." + e.lower() for e in extensions.split()] + [
|
||||||
map(lambda e: "*" + e, covers.EXTENSIONS)
|
"*" + e for e in covers.EXTENSIONS
|
||||||
)
|
]
|
||||||
super().__init__(patterns=patterns, ignore_directories=True)
|
super().__init__(patterns=patterns, ignore_directories=True)
|
||||||
|
|
||||||
def dispatch(self, event):
|
def dispatch(self, event):
|
||||||
@ -132,7 +132,7 @@ class ScannerProcessingQueue(Thread):
|
|||||||
self.__timeout = delay
|
self.__timeout = delay
|
||||||
self.__cond = Condition()
|
self.__cond = Condition()
|
||||||
self.__timer = None
|
self.__timer = None
|
||||||
self.__queue = dict()
|
self.__queue = {}
|
||||||
self.__running = True
|
self.__running = True
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
@ -172,7 +172,7 @@ class PlaylistTestCase(ApiTestBase):
|
|||||||
"createPlaylist",
|
"createPlaylist",
|
||||||
{
|
{
|
||||||
"name": "songs",
|
"name": "songs",
|
||||||
"songId": list(map(lambda s: songs[s], ["Three", "One", "Two"])),
|
"songId": [songs[s] for s in ("Three", "One", "Two")],
|
||||||
},
|
},
|
||||||
skip_post=True,
|
skip_post=True,
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user