1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-11-14 22:22:18 +00:00
supysonic/api/browse.py

177 lines
5.1 KiB
Python
Raw Normal View History

2012-10-13 09:29:48 +00:00
# coding: utf-8
from flask import request
from web import app
from db import Folder, Artist, Album, Track, func, session
2012-12-02 15:42:25 +00:00
from api import get_entity
import uuid, time, string
import os.path
2012-10-13 09:29:48 +00:00
2012-11-22 13:51:43 +00:00
@app.route('/rest/getMusicFolders.view', methods = [ 'GET', 'POST' ])
2012-10-13 09:29:48 +00:00
def list_folders():
return request.formatter({
'musicFolders': {
'musicFolder': [ {
'id': str(f.id),
'name': f.name
} for f in Folder.query.filter(Folder.root == True).order_by(Folder.path).all() ]
2012-10-13 09:29:48 +00:00
}
})
2012-11-22 13:51:43 +00:00
@app.route('/rest/getIndexes.view', methods = [ 'GET', 'POST' ])
def list_indexes():
musicFolderId = request.args.get('musicFolderId')
ifModifiedSince = request.args.get('ifModifiedSince')
if ifModifiedSince:
try:
ifModifiedSince = int(ifModifiedSince) / 1000
except:
return request.error_formatter(0, 'Invalid timestamp')
if musicFolderId is None:
2012-10-21 14:18:35 +00:00
folder = Folder.query.filter(Folder.root == True).all()
else:
try:
mfid = uuid.UUID(musicFolderId)
except:
return request.error_formatter(0, 'Invalid id')
2012-10-21 14:18:35 +00:00
folder = Folder.query.get(mfid)
2012-11-11 20:39:26 +00:00
if not folder or (type(folder) is not list and not folder.root):
return request.error_formatter(70, 'Folder not found')
last_modif = max(map(lambda f: f.last_scan, folder)) if type(folder) is list else folder.last_scan
if (not ifModifiedSince is None) and last_modif < ifModifiedSince:
return request.formatter({ 'indexes': { 'lastModified': last_modif * 1000 } })
# The XSD lies, we don't return artists but a directory structure
if type(folder) is list:
artists = []
childs = []
for f in folder:
artists += f.get_children()
childs += f.tracks
else:
artists = folder.get_children()
childs = folder.tracks
indexes = {}
for artist in artists:
index = artist.name[0].upper()
if index in map(str, xrange(10)):
index = '#'
elif index not in string.letters:
index = '?'
if index not in indexes:
indexes[index] = []
indexes[index].append(artist)
return request.formatter({
'indexes': {
'lastModified': last_modif * 1000,
'index': [ {
'name': k,
'artist': [ {
'id': str(a.id),
'name': a.name
} for a in sorted(v, key = lambda a: a.name.lower()) ]
} for k, v in sorted(indexes.iteritems()) ],
2013-06-13 16:44:56 +00:00
'child': [ c.as_subsonic_child(request.user) for c in sorted(childs, key = lambda t: t.sort_key()) ]
}
})
2012-11-22 13:51:43 +00:00
@app.route('/rest/getMusicDirectory.view', methods = [ 'GET', 'POST' ])
2012-11-10 23:01:52 +00:00
def show_directory():
2012-12-02 15:42:25 +00:00
status, res = get_entity(request, Folder)
if not status:
return res
2012-11-10 23:01:52 +00:00
res.tracks = [t for t in res.tracks if os.path.isfile(t.path)]
2012-11-10 23:01:52 +00:00
directory = {
2012-12-02 15:42:25 +00:00
'id': str(res.id),
'name': res.name,
'child': [ f.as_subsonic_child(request.user) for f in res.get_children() ] + [ t.as_subsonic_child(request.user) for t in sorted(res.tracks, key = lambda t: t.sort_key()) ]
2012-11-10 23:01:52 +00:00
}
2012-12-02 15:42:25 +00:00
if not res.root:
parent = Folder.query.with_entities(Folder.id) \
.filter(Folder.path.like(res.path[:len(res.path)-len(res.name)-1])) \
.order_by(func.length(Folder.path).desc()).first()
if parent:
directory['parent'] = str(parent.id)
2012-11-10 23:01:52 +00:00
return request.formatter({ 'directory': directory })
@app.route('/rest/getArtists.view', methods = [ 'GET', 'POST' ])
def list_artists():
2012-12-02 15:42:25 +00:00
# According to the API page, there are no parameters?
indexes = {}
# Optimized query instead of using backrefs, is there a way to speed up the backref?
c = session.query(Album.artist_id, func.count(Album.artist_id).label('c')).group_by(Album.artist_id).subquery(name='c')
for artist in session.query(Artist.name, Artist.id, c.c.c.label('albums')).join(c).order_by(Artist.name).all():
2013-10-26 11:13:19 +00:00
index = artist.name[0].upper() if artist.name else '?'
if index in map(str, xrange(10)):
index = '#'
elif index not in string.letters:
index = '?'
if index not in indexes:
indexes[index] = []
indexes[index].append(artist)
return request.formatter({
'artists': {
'index': [ {
'name': k,
'artist': [ {
'id': str(a.id),
'name': a.name,
'albumCount': a.albums
} for a in v ]
} for k, v in sorted(indexes.iteritems()) ]
}
})
@app.route('/rest/getArtist.view', methods = [ 'GET', 'POST' ])
def artist_info():
2012-12-02 15:42:25 +00:00
status, res = get_entity(request, Artist)
if not status:
return res
2013-06-13 16:44:56 +00:00
info = res.as_subsonic_artist(request.user)
info['album'] = [ a.as_subsonic_album(request.user) for a in sorted(res.albums, key = lambda a: a.sort_key()) ]
return request.formatter({ 'artist': info })
@app.route('/rest/getAlbum.view', methods = [ 'GET', 'POST' ])
def album_info():
2012-12-02 15:42:25 +00:00
status, res = get_entity(request, Album)
if not status:
return res
2013-06-13 16:44:56 +00:00
info = res.as_subsonic_album(request.user)
info['song'] = [ t.as_subsonic_child(request.user) for t in sorted(res.tracks, key = lambda t: t.sort_key()) ]
2012-12-02 15:42:25 +00:00
return request.formatter({ 'album': info })
2012-12-01 19:12:35 +00:00
@app.route('/rest/getSong.view', methods = [ 'GET', 'POST' ])
def track_info():
2012-12-02 15:42:25 +00:00
status, res = get_entity(request, Track)
if not status:
return res
2012-12-01 19:12:35 +00:00
2013-06-13 16:44:56 +00:00
return request.formatter({ 'song': res.as_subsonic_child(request.user) })
@app.route('/rest/getVideos.view', methods = [ 'GET', 'POST' ])
def list_videos():
return request.error_formatter(0, 'Video streaming not supported')