Begin abstracting api responses
This commit is contained in:
parent
7c9b1d7869
commit
73f0ff1201
102
pysonic/api.py
102
pysonic/api.py
|
@ -1,11 +1,11 @@
|
|||
import sys
|
||||
import json
|
||||
import logging
|
||||
import cherrypy
|
||||
import subprocess
|
||||
from time import time
|
||||
from random import shuffle
|
||||
from threading import Thread
|
||||
from time import sleep
|
||||
import cherrypy
|
||||
from collections import defaultdict
|
||||
from bs4 import BeautifulSoup
|
||||
from pysonic.library import LETTER_GROUPS
|
||||
from pysonic.types import MUSIC_TYPES
|
||||
|
@ -14,6 +14,65 @@ from pysonic.types import MUSIC_TYPES
|
|||
logging = logging.getLogger("api")
|
||||
|
||||
|
||||
class ApiResponse(object):
|
||||
def __init__(self, status="ok", version="1.15.0", top=None, **kwargs):
|
||||
self.status = status
|
||||
self.version = version
|
||||
self.data = {}
|
||||
self.top = top
|
||||
if self.top:
|
||||
self.data[self.top] = kwargs ## kwargs unused TODO
|
||||
|
||||
def add_child(self, _type, **kwargs):
|
||||
if not self.top:
|
||||
raise Exception("You can't do this?")
|
||||
if _type not in self.data[self.top]:
|
||||
self.data[self.top][_type] = []
|
||||
self.data[self.top][_type].append(kwargs)
|
||||
|
||||
def render_json(self):
|
||||
return json.dumps({"subsonic-response": dict(status=self.status, version="1.15.0", **self.data)}, indent=4)
|
||||
|
||||
def render_xml(self):
|
||||
doc = BeautifulSoup('', features='lxml-xml')
|
||||
root = doc.new_tag("subsonic-response", xmlns="http://subsonic.org/restapi",
|
||||
status=self.status,
|
||||
version=self.version)
|
||||
doc.append(root)
|
||||
|
||||
if self.top:
|
||||
top = doc.new_tag(self.top)
|
||||
root.append(top)
|
||||
# TODO top_attrs ?
|
||||
for top_child_type, top_child_instances in self.data[self.top].items():
|
||||
for top_child_attrs in top_child_instances:
|
||||
child = doc.new_tag(top_child_type)
|
||||
child.attrs.update(top_child_attrs)
|
||||
top.append(child)
|
||||
|
||||
albumlist = doc.new_tag("albumList")
|
||||
doc.append(albumlist)
|
||||
return doc.prettify()
|
||||
|
||||
|
||||
response_formats = defaultdict(lambda: "render_xml")
|
||||
response_formats["json"] = "render_json"
|
||||
|
||||
response_headers = defaultdict(lambda: "text/xml; charset=utf-8")
|
||||
response_headers["json"] = "text/json" #TODO is this right?
|
||||
|
||||
|
||||
def formatresponse(func):
|
||||
"""
|
||||
Decorator for rendering ApiResponse responses
|
||||
"""
|
||||
def wrapper(*args, **kwargs):
|
||||
response = func(*args, **kwargs)
|
||||
cherrypy.response.headers['Content-Type'] = response_headers[kwargs.get("f", "xml")]
|
||||
return getattr(response, response_formats[kwargs.get("f", "xml")])()
|
||||
return wrapper
|
||||
|
||||
|
||||
class PysonicApi(object):
|
||||
def __init__(self, db, library, options):
|
||||
self.db = db
|
||||
|
@ -104,6 +163,7 @@ class PysonicApi(object):
|
|||
print("TODO save playlist with items {} current {} position {}".format(id, current, position))
|
||||
|
||||
@cherrypy.expose
|
||||
@formatresponse
|
||||
def getAlbumList_view(self, type, size=50, offset=0, **kwargs):
|
||||
albums = self.library.get_albums()
|
||||
if type == "random":
|
||||
|
@ -114,31 +174,27 @@ class PysonicApi(object):
|
|||
raise NotImplemented()
|
||||
albumset = albums[0 + int(offset):int(size) + int(offset)]
|
||||
|
||||
cherrypy.response.headers['Content-Type'] = 'text/xml; charset=utf-8'
|
||||
doc, root = self.response()
|
||||
albumlist = doc.new_tag("albumList")
|
||||
doc.append(albumlist)
|
||||
response = ApiResponse(top="albumList")
|
||||
|
||||
for album in albumset:
|
||||
album_meta = album['metadata']
|
||||
tag = doc.new_tag("album",
|
||||
id=album["id"],
|
||||
parent=album["parent"],
|
||||
isDir="true" if album['isdir'] else "false",
|
||||
title=album_meta.get("id3_title", album["name"]), #TODO these cant be blank or dsub gets mad
|
||||
album=album_meta.get("id3_album", album["album"]),
|
||||
artist=album_meta.get("id3_artist", album["artist"]),
|
||||
# X year="2014"
|
||||
# X coverArt="3228"
|
||||
# playCount="0"
|
||||
# created="2016-05-08T05:31:31.000Z"/>
|
||||
)
|
||||
album_kw = dict(id=album["id"],
|
||||
parent=album["parent"],
|
||||
isDir="true" if album['isdir'] else "false",
|
||||
title=album_meta.get("id3_title", album["name"]), #TODO these cant be blank or dsub gets mad
|
||||
album=album_meta.get("id3_album", album["album"]),
|
||||
artist=album_meta.get("id3_artist", album["artist"]),
|
||||
# X year="2014"
|
||||
# X coverArt="3228"
|
||||
# playCount="0"
|
||||
# created="2016-05-08T05:31:31.000Z"/>)
|
||||
)
|
||||
if 'cover' in album_meta:
|
||||
tag.attrs["coverArt"] = album_meta["cover"]
|
||||
album_kw["coverArt"] = album_meta["cover"]
|
||||
if 'id3_year' in album_meta:
|
||||
tag.attrs["year"] = album_meta['id3_year']
|
||||
albumlist.append(tag)
|
||||
yield doc.prettify()
|
||||
album_kw["year"] = album_meta['id3_year']
|
||||
response.add_child("album", **album_kw)
|
||||
return response
|
||||
|
||||
@cherrypy.expose
|
||||
def getMusicDirectory_view(self, id, **kwargs):
|
||||
|
|
Loading…
Reference in New Issue