mirror of
https://github.com/spl0k/supysonic.git
synced 2024-12-23 01:16:18 +00:00
parent
aedda4f642
commit
0de87e64b0
@ -24,7 +24,7 @@ import binascii
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from flask import request
|
from flask import request
|
||||||
from flask import current_app as app
|
from flask import Blueprint
|
||||||
from pony.orm import db_session, ObjectNotFound
|
from pony.orm import db_session, ObjectNotFound
|
||||||
|
|
||||||
from ..managers.user import UserManager
|
from ..managers.user import UserManager
|
||||||
@ -33,11 +33,10 @@ from ..py23 import dict
|
|||||||
from .formatters import make_json_response, make_jsonp_response, make_xml_response
|
from .formatters import make_json_response, make_jsonp_response, make_xml_response
|
||||||
from .formatters import make_error_response_func
|
from .formatters import make_error_response_func
|
||||||
|
|
||||||
@app.before_request
|
api = Blueprint('api', __name__)
|
||||||
def set_formatter():
|
|
||||||
if not request.path.startswith('/rest/'):
|
|
||||||
return
|
|
||||||
|
|
||||||
|
@api.before_request
|
||||||
|
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':
|
||||||
@ -58,11 +57,8 @@ def decode_password(password):
|
|||||||
except:
|
except:
|
||||||
return password
|
return password
|
||||||
|
|
||||||
@app.before_request
|
@api.before_request
|
||||||
def authorize():
|
def authorize():
|
||||||
if not request.path.startswith('/rest/'):
|
|
||||||
return
|
|
||||||
|
|
||||||
error = request.error_formatter(40, 'Unauthorized'), 401
|
error = request.error_formatter(40, 'Unauthorized'), 401
|
||||||
|
|
||||||
if request.authorization:
|
if request.authorization:
|
||||||
@ -84,11 +80,8 @@ def authorize():
|
|||||||
request.username = username
|
request.username = username
|
||||||
request.user = user
|
request.user = user
|
||||||
|
|
||||||
@app.before_request
|
@api.before_request
|
||||||
def get_client_prefs():
|
def get_client_prefs():
|
||||||
if not request.path.startswith('/rest/'):
|
|
||||||
return
|
|
||||||
|
|
||||||
if 'c' not in request.values:
|
if 'c' not in request.values:
|
||||||
return request.error_formatter(10, 'Missing required parameter')
|
return request.error_formatter(10, 'Missing required parameter')
|
||||||
|
|
||||||
@ -101,11 +94,9 @@ def get_client_prefs():
|
|||||||
|
|
||||||
request.client = client
|
request.client = client
|
||||||
|
|
||||||
@app.errorhandler(404)
|
#@api.errorhandler(404)
|
||||||
def not_found(error):
|
@api.route('/<path:invalid>', methods = [ 'GET', 'POST' ]) # blueprint 404 workaround
|
||||||
if not request.path.startswith('/rest/'):
|
def not_found(*args, **kwargs):
|
||||||
return error
|
|
||||||
|
|
||||||
return request.error_formatter(0, 'Not implemented'), 501
|
return request.error_formatter(0, 'Not implemented'), 501
|
||||||
|
|
||||||
def get_entity(req, cls, param = 'id'):
|
def get_entity(req, cls, param = 'id'):
|
||||||
|
@ -22,14 +22,15 @@ import random
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from flask import request, current_app as app
|
from flask import request
|
||||||
from pony.orm import db_session, select, desc, avg, max, min, count
|
from pony.orm import db_session, select, desc, avg, max, min, count
|
||||||
|
|
||||||
from ..db import Folder, Artist, Album, Track, RatingFolder, StarredFolder, StarredArtist, StarredAlbum, StarredTrack, User
|
from ..db import Folder, Artist, Album, Track, RatingFolder, StarredFolder, StarredArtist, StarredAlbum, StarredTrack, User
|
||||||
from ..db import now
|
from ..db import now
|
||||||
from ..py23 import dict
|
from ..py23 import dict
|
||||||
|
from . import api
|
||||||
|
|
||||||
@app.route('/rest/getRandomSongs.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getRandomSongs.view', methods = [ 'GET', 'POST' ])
|
||||||
def rand_songs():
|
def rand_songs():
|
||||||
size = request.values.get('size', '10')
|
size = request.values.get('size', '10')
|
||||||
genre, fromYear, toYear, musicFolderId = map(request.values.get, [ 'genre', 'fromYear', 'toYear', 'musicFolderId' ])
|
genre, fromYear, toYear, musicFolderId = map(request.values.get, [ 'genre', 'fromYear', 'toYear', 'musicFolderId' ])
|
||||||
@ -63,7 +64,7 @@ def rand_songs():
|
|||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
@app.route('/rest/getAlbumList.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getAlbumList.view', methods = [ 'GET', 'POST' ])
|
||||||
def album_list():
|
def album_list():
|
||||||
ltype, size, offset = map(request.values.get, [ 'type', 'size', 'offset' ])
|
ltype, size, offset = map(request.values.get, [ 'type', 'size', 'offset' ])
|
||||||
if not ltype:
|
if not ltype:
|
||||||
@ -106,7 +107,7 @@ def album_list():
|
|||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
@app.route('/rest/getAlbumList2.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getAlbumList2.view', methods = [ 'GET', 'POST' ])
|
||||||
def album_list_id3():
|
def album_list_id3():
|
||||||
ltype, size, offset = map(request.values.get, [ 'type', 'size', 'offset' ])
|
ltype, size, offset = map(request.values.get, [ 'type', 'size', 'offset' ])
|
||||||
if not ltype:
|
if not ltype:
|
||||||
@ -147,7 +148,7 @@ def album_list_id3():
|
|||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
@app.route('/rest/getNowPlaying.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getNowPlaying.view', methods = [ 'GET', 'POST' ])
|
||||||
@db_session
|
@db_session
|
||||||
def now_playing():
|
def now_playing():
|
||||||
query = User.select(lambda u: u.last_play is not None and u.last_play_date + timedelta(minutes = 3) > now())
|
query = User.select(lambda u: u.last_play is not None and u.last_play_date + timedelta(minutes = 3) > now())
|
||||||
@ -161,7 +162,7 @@ def now_playing():
|
|||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
@app.route('/rest/getStarred.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getStarred.view', methods = [ 'GET', 'POST' ])
|
||||||
@db_session
|
@db_session
|
||||||
def get_starred():
|
def get_starred():
|
||||||
folders = select(s.starred for s in StarredFolder if s.user.id == request.user.id)
|
folders = select(s.starred for s in StarredFolder if s.user.id == request.user.id)
|
||||||
@ -174,7 +175,7 @@ def get_starred():
|
|||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
@app.route('/rest/getStarred2.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getStarred2.view', methods = [ 'GET', 'POST' ])
|
||||||
@db_session
|
@db_session
|
||||||
def get_starred_id3():
|
def get_starred_id3():
|
||||||
return request.formatter(dict(
|
return request.formatter(dict(
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
import time
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from flask import request, current_app as app
|
from flask import current_app, request
|
||||||
from pony.orm import db_session, delete
|
from pony.orm import db_session, delete
|
||||||
from pony.orm import ObjectNotFound
|
from pony.orm import ObjectNotFound
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ from ..db import RatingTrack, RatingFolder
|
|||||||
from ..lastfm import LastFm
|
from ..lastfm import LastFm
|
||||||
from ..py23 import dict
|
from ..py23 import dict
|
||||||
|
|
||||||
from . import get_entity
|
from . import api, get_entity
|
||||||
|
|
||||||
@db_session
|
@db_session
|
||||||
def try_star(cls, starred_cls, eid):
|
def try_star(cls, starred_cls, eid):
|
||||||
@ -88,7 +88,7 @@ def merge_errors(errors):
|
|||||||
|
|
||||||
return error
|
return error
|
||||||
|
|
||||||
@app.route('/rest/star.view', methods = [ 'GET', 'POST' ])
|
@api.route('/star.view', methods = [ 'GET', 'POST' ])
|
||||||
def star():
|
def star():
|
||||||
id, albumId, artistId = map(request.values.getlist, [ 'id', 'albumId', 'artistId' ])
|
id, albumId, artistId = map(request.values.getlist, [ 'id', 'albumId', 'artistId' ])
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ def star():
|
|||||||
error = merge_errors(errors)
|
error = merge_errors(errors)
|
||||||
return request.formatter(dict(error = error), error = True) if error else request.formatter(dict())
|
return request.formatter(dict(error = error), error = True) if error else request.formatter(dict())
|
||||||
|
|
||||||
@app.route('/rest/unstar.view', methods = [ 'GET', 'POST' ])
|
@api.route('/unstar.view', methods = [ 'GET', 'POST' ])
|
||||||
def unstar():
|
def unstar():
|
||||||
id, albumId, artistId = map(request.values.getlist, [ 'id', 'albumId', 'artistId' ])
|
id, albumId, artistId = map(request.values.getlist, [ 'id', 'albumId', 'artistId' ])
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ def unstar():
|
|||||||
error = merge_errors(errors)
|
error = merge_errors(errors)
|
||||||
return request.formatter(dict(error = error), error = True) if error else request.formatter(dict())
|
return request.formatter(dict(error = error), error = True) if error else request.formatter(dict())
|
||||||
|
|
||||||
@app.route('/rest/setRating.view', methods = [ 'GET', 'POST' ])
|
@api.route('/setRating.view', methods = [ 'GET', 'POST' ])
|
||||||
def rate():
|
def rate():
|
||||||
id, rating = map(request.values.get, [ 'id', 'rating' ])
|
id, rating = map(request.values.get, [ 'id', 'rating' ])
|
||||||
if not id or not rating:
|
if not id or not rating:
|
||||||
@ -172,7 +172,7 @@ def rate():
|
|||||||
|
|
||||||
return request.formatter(dict())
|
return request.formatter(dict())
|
||||||
|
|
||||||
@app.route('/rest/scrobble.view', methods = [ 'GET', 'POST' ])
|
@api.route('/scrobble.view', methods = [ 'GET', 'POST' ])
|
||||||
@db_session
|
@db_session
|
||||||
def scrobble():
|
def scrobble():
|
||||||
status, res = get_entity(request, Track)
|
status, res = get_entity(request, Track)
|
||||||
@ -189,7 +189,7 @@ def scrobble():
|
|||||||
else:
|
else:
|
||||||
t = int(time.time())
|
t = int(time.time())
|
||||||
|
|
||||||
lfm = LastFm(app.config['LASTFM'], User[request.user.id], app.logger)
|
lfm = LastFm(current_app.config['LASTFM'], User[request.user.id], current_app.logger)
|
||||||
|
|
||||||
if submission in (None, '', True, 'true', 'True', 1, '1'):
|
if submission in (None, '', True, 'true', 'True', 1, '1'):
|
||||||
lfm.scrobble(res, t)
|
lfm.scrobble(res, t)
|
||||||
|
@ -21,16 +21,16 @@
|
|||||||
import string
|
import string
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from flask import request, current_app as app
|
from flask import request
|
||||||
from pony.orm import db_session
|
from pony.orm import db_session
|
||||||
from pony.orm import ObjectNotFound
|
from pony.orm import ObjectNotFound
|
||||||
|
|
||||||
from ..db import Folder, Artist, Album, Track
|
from ..db import Folder, Artist, Album, Track
|
||||||
from ..py23 import dict
|
from ..py23 import dict
|
||||||
|
|
||||||
from . import get_entity
|
from . import api, get_entity
|
||||||
|
|
||||||
@app.route('/rest/getMusicFolders.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getMusicFolders.view', methods = [ 'GET', 'POST' ])
|
||||||
@db_session
|
@db_session
|
||||||
def list_folders():
|
def list_folders():
|
||||||
return request.formatter(dict(
|
return request.formatter(dict(
|
||||||
@ -42,7 +42,7 @@ def list_folders():
|
|||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
@app.route('/rest/getIndexes.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getIndexes.view', methods = [ 'GET', 'POST' ])
|
||||||
@db_session
|
@db_session
|
||||||
def list_indexes():
|
def list_indexes():
|
||||||
musicFolderId = request.values.get('musicFolderId')
|
musicFolderId = request.values.get('musicFolderId')
|
||||||
@ -105,7 +105,7 @@ def list_indexes():
|
|||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
@app.route('/rest/getMusicDirectory.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getMusicDirectory.view', methods = [ 'GET', 'POST' ])
|
||||||
@db_session
|
@db_session
|
||||||
def show_directory():
|
def show_directory():
|
||||||
status, res = get_entity(request, Folder)
|
status, res = get_entity(request, Folder)
|
||||||
@ -122,7 +122,7 @@ def show_directory():
|
|||||||
|
|
||||||
return request.formatter(dict(directory = directory))
|
return request.formatter(dict(directory = directory))
|
||||||
|
|
||||||
@app.route('/rest/getArtists.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getArtists.view', methods = [ 'GET', 'POST' ])
|
||||||
@db_session
|
@db_session
|
||||||
def list_artists():
|
def list_artists():
|
||||||
# According to the API page, there are no parameters?
|
# According to the API page, there are no parameters?
|
||||||
@ -148,7 +148,7 @@ def list_artists():
|
|||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
@app.route('/rest/getArtist.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getArtist.view', methods = [ 'GET', 'POST' ])
|
||||||
@db_session
|
@db_session
|
||||||
def artist_info():
|
def artist_info():
|
||||||
status, res = get_entity(request, Artist)
|
status, res = get_entity(request, Artist)
|
||||||
@ -162,7 +162,7 @@ def artist_info():
|
|||||||
|
|
||||||
return request.formatter(dict(artist = info))
|
return request.formatter(dict(artist = info))
|
||||||
|
|
||||||
@app.route('/rest/getAlbum.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getAlbum.view', methods = [ 'GET', 'POST' ])
|
||||||
@db_session
|
@db_session
|
||||||
def album_info():
|
def album_info():
|
||||||
status, res = get_entity(request, Album)
|
status, res = get_entity(request, Album)
|
||||||
@ -174,7 +174,7 @@ def album_info():
|
|||||||
|
|
||||||
return request.formatter(dict(album = info))
|
return request.formatter(dict(album = info))
|
||||||
|
|
||||||
@app.route('/rest/getSong.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getSong.view', methods = [ 'GET', 'POST' ])
|
||||||
@db_session
|
@db_session
|
||||||
def track_info():
|
def track_info():
|
||||||
status, res = get_entity(request, Track)
|
status, res = get_entity(request, Track)
|
||||||
@ -183,7 +183,7 @@ def track_info():
|
|||||||
|
|
||||||
return request.formatter(dict(song = res.as_subsonic_child(request.user, request.client)))
|
return request.formatter(dict(song = res.as_subsonic_child(request.user, request.client)))
|
||||||
|
|
||||||
@app.route('/rest/getVideos.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getVideos.view', methods = [ 'GET', 'POST' ])
|
||||||
def list_videos():
|
def list_videos():
|
||||||
return request.error_formatter(0, 'Video streaming not supported')
|
return request.error_formatter(0, 'Video streaming not supported')
|
||||||
|
|
||||||
|
@ -18,13 +18,14 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from flask import request, current_app as app
|
from flask import request
|
||||||
from pony.orm import db_session
|
from pony.orm import db_session
|
||||||
|
|
||||||
from ..db import ChatMessage, User
|
from ..db import ChatMessage, User
|
||||||
from ..py23 import dict
|
from ..py23 import dict
|
||||||
|
from . import api
|
||||||
|
|
||||||
@app.route('/rest/getChatMessages.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getChatMessages.view', methods = [ 'GET', 'POST' ])
|
||||||
def get_chat():
|
def get_chat():
|
||||||
since = request.values.get('since')
|
since = request.values.get('since')
|
||||||
try:
|
try:
|
||||||
@ -39,7 +40,7 @@ def get_chat():
|
|||||||
|
|
||||||
return request.formatter(dict(chatMessages = dict(chatMessage = [ msg.responsize() for msg in query ] )))
|
return request.formatter(dict(chatMessages = dict(chatMessage = [ msg.responsize() for msg in query ] )))
|
||||||
|
|
||||||
@app.route('/rest/addChatMessage.view', methods = [ 'GET', 'POST' ])
|
@api.route('/addChatMessage.view', methods = [ 'GET', 'POST' ])
|
||||||
def add_chat_message():
|
def add_chat_message():
|
||||||
msg = request.values.get('message')
|
msg = request.values.get('message')
|
||||||
if not msg:
|
if not msg:
|
||||||
|
@ -24,7 +24,8 @@ import os.path
|
|||||||
import requests
|
import requests
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from flask import request, send_file, Response, current_app as app
|
from flask import request, Response, send_file
|
||||||
|
from flask import current_app
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from pony.orm import db_session
|
from pony.orm import db_session
|
||||||
from xml.etree import ElementTree
|
from xml.etree import ElementTree
|
||||||
@ -33,7 +34,7 @@ from .. import scanner
|
|||||||
from ..db import Track, Album, Artist, Folder, User, ClientPrefs, now
|
from ..db import Track, Album, Artist, Folder, User, ClientPrefs, now
|
||||||
from ..py23 import dict
|
from ..py23 import dict
|
||||||
|
|
||||||
from . import get_entity
|
from . import api, get_entity
|
||||||
|
|
||||||
def prepare_transcoding_cmdline(base_cmdline, input_file, input_format, output_format, output_bitrate):
|
def prepare_transcoding_cmdline(base_cmdline, input_file, input_format, output_format, output_bitrate):
|
||||||
if not base_cmdline:
|
if not base_cmdline:
|
||||||
@ -45,7 +46,7 @@ def prepare_transcoding_cmdline(base_cmdline, input_file, input_format, output_f
|
|||||||
]
|
]
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@app.route('/rest/stream.view', methods = [ 'GET', 'POST' ])
|
@api.route('/stream.view', methods = [ 'GET', 'POST' ])
|
||||||
@db_session
|
@db_session
|
||||||
def stream_media():
|
def stream_media():
|
||||||
status, res = get_entity(request, Track)
|
status, res = get_entity(request, Track)
|
||||||
@ -81,7 +82,7 @@ def stream_media():
|
|||||||
dst_mimetype = mimetypes.guess_type('dummyname.' + dst_suffix, False)[0] or 'application/octet-stream'
|
dst_mimetype = mimetypes.guess_type('dummyname.' + dst_suffix, False)[0] or 'application/octet-stream'
|
||||||
|
|
||||||
if format != 'raw' and (dst_suffix != src_suffix or dst_bitrate != res.bitrate):
|
if format != 'raw' and (dst_suffix != src_suffix or dst_bitrate != res.bitrate):
|
||||||
config = app.config['TRANSCODING']
|
config = current_app.config['TRANSCODING']
|
||||||
transcoder = config.get('transcoder_{}_{}'.format(src_suffix, dst_suffix))
|
transcoder = config.get('transcoder_{}_{}'.format(src_suffix, dst_suffix))
|
||||||
decoder = config.get('decoder_' + src_suffix) or config.get('decoder')
|
decoder = config.get('decoder_' + src_suffix) or config.get('decoder')
|
||||||
encoder = config.get('encoder_' + dst_suffix) or config.get('encoder')
|
encoder = config.get('encoder_' + dst_suffix) or config.get('encoder')
|
||||||
@ -89,7 +90,7 @@ def stream_media():
|
|||||||
transcoder = config.get('transcoder')
|
transcoder = config.get('transcoder')
|
||||||
if not transcoder:
|
if not transcoder:
|
||||||
message = 'No way to transcode from {} to {}'.format(src_suffix, dst_suffix)
|
message = 'No way to transcode from {} to {}'.format(src_suffix, dst_suffix)
|
||||||
app.logger.info(message)
|
current_app.logger.info(message)
|
||||||
return request.error_formatter(0, message)
|
return request.error_formatter(0, message)
|
||||||
|
|
||||||
transcoder, decoder, encoder = map(lambda x: prepare_transcoding_cmdline(x, res.path, src_suffix, dst_suffix, dst_bitrate), [ transcoder, decoder, encoder ])
|
transcoder, decoder, encoder = map(lambda x: prepare_transcoding_cmdline(x, res.path, src_suffix, dst_suffix, dst_bitrate), [ transcoder, decoder, encoder ])
|
||||||
@ -119,7 +120,7 @@ def stream_media():
|
|||||||
dec_proc.wait()
|
dec_proc.wait()
|
||||||
proc.wait()
|
proc.wait()
|
||||||
|
|
||||||
app.logger.info('Transcoding track {0.id} for user {1.id}. Source: {2} at {0.bitrate}kbps. Dest: {3} at {4}kbps'.format(res, request.user, src_suffix, dst_suffix, dst_bitrate))
|
current_app.logger.info('Transcoding track {0.id} for user {1.id}. Source: {2} at {0.bitrate}kbps. Dest: {3} at {4}kbps'.format(res, request.user, src_suffix, dst_suffix, dst_bitrate))
|
||||||
response = Response(transcode(), mimetype = dst_mimetype)
|
response = Response(transcode(), mimetype = dst_mimetype)
|
||||||
else:
|
else:
|
||||||
response = send_file(res.path, mimetype = dst_mimetype, conditional=True)
|
response = send_file(res.path, mimetype = dst_mimetype, conditional=True)
|
||||||
@ -132,7 +133,7 @@ def stream_media():
|
|||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@app.route('/rest/download.view', methods = [ 'GET', 'POST' ])
|
@api.route('/download.view', methods = [ 'GET', 'POST' ])
|
||||||
def download_media():
|
def download_media():
|
||||||
with db_session:
|
with db_session:
|
||||||
status, res = get_entity(request, Track)
|
status, res = get_entity(request, Track)
|
||||||
@ -141,7 +142,7 @@ def download_media():
|
|||||||
|
|
||||||
return send_file(res.path, mimetype = res.content_type, conditional=True)
|
return send_file(res.path, mimetype = res.content_type, conditional=True)
|
||||||
|
|
||||||
@app.route('/rest/getCoverArt.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getCoverArt.view', methods = [ 'GET', 'POST' ])
|
||||||
def cover_art():
|
def cover_art():
|
||||||
with db_session:
|
with db_session:
|
||||||
status, res = get_entity(request, Folder)
|
status, res = get_entity(request, Folder)
|
||||||
@ -164,7 +165,7 @@ def cover_art():
|
|||||||
if size > im.size[0] and size > im.size[1]:
|
if size > im.size[0] and size > im.size[1]:
|
||||||
return send_file(os.path.join(res.path, 'cover.jpg'))
|
return send_file(os.path.join(res.path, 'cover.jpg'))
|
||||||
|
|
||||||
size_path = os.path.join(app.config['WEBAPP']['cache_dir'], str(size))
|
size_path = os.path.join(current_app.config['WEBAPP']['cache_dir'], str(size))
|
||||||
path = os.path.abspath(os.path.join(size_path, str(res.id)))
|
path = os.path.abspath(os.path.join(size_path, str(res.id)))
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
return send_file(path, mimetype = 'image/jpeg')
|
return send_file(path, mimetype = 'image/jpeg')
|
||||||
@ -175,7 +176,7 @@ def cover_art():
|
|||||||
im.save(path, 'JPEG')
|
im.save(path, 'JPEG')
|
||||||
return send_file(path, mimetype = 'image/jpeg')
|
return send_file(path, mimetype = 'image/jpeg')
|
||||||
|
|
||||||
@app.route('/rest/getLyrics.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getLyrics.view', methods = [ 'GET', 'POST' ])
|
||||||
def lyrics():
|
def lyrics():
|
||||||
artist, title = map(request.values.get, [ 'artist', 'title' ])
|
artist, title = map(request.values.get, [ 'artist', 'title' ])
|
||||||
if not artist:
|
if not artist:
|
||||||
@ -188,14 +189,14 @@ def lyrics():
|
|||||||
for track in query:
|
for track in query:
|
||||||
lyrics_path = os.path.splitext(track.path)[0] + '.txt'
|
lyrics_path = os.path.splitext(track.path)[0] + '.txt'
|
||||||
if os.path.exists(lyrics_path):
|
if os.path.exists(lyrics_path):
|
||||||
app.logger.debug('Found lyrics file: ' + lyrics_path)
|
current_app.logger.debug('Found lyrics file: ' + lyrics_path)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
lyrics = read_file_as_unicode(lyrics_path)
|
lyrics = read_file_as_unicode(lyrics_path)
|
||||||
except UnicodeError:
|
except UnicodeError:
|
||||||
# Lyrics file couldn't be decoded. Rather than displaying an error, try with the potential next files or
|
# Lyrics file couldn't be decoded. Rather than displaying an error, try with the potential next files or
|
||||||
# return no lyrics. Log it anyway.
|
# return no lyrics. Log it anyway.
|
||||||
app.logger.warning('Unsupported encoding for lyrics file ' + lyrics_path)
|
current_app.logger.warning('Unsupported encoding for lyrics file ' + lyrics_path)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return request.formatter(dict(lyrics = dict(
|
return request.formatter(dict(lyrics = dict(
|
||||||
@ -216,7 +217,7 @@ def lyrics():
|
|||||||
_value_ = root.find('cl:Lyric', namespaces = ns).text
|
_value_ = root.find('cl:Lyric', namespaces = ns).text
|
||||||
)))
|
)))
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
app.logger.warning('Error while requesting the ChartLyrics API: ' + str(e))
|
current_app.logger.warning('Error while requesting the ChartLyrics API: ' + str(e))
|
||||||
|
|
||||||
return request.formatter(dict(lyrics = dict()))
|
return request.formatter(dict(lyrics = dict()))
|
||||||
|
|
||||||
@ -228,13 +229,13 @@ def read_file_as_unicode(path):
|
|||||||
for enc in encodings:
|
for enc in encodings:
|
||||||
try:
|
try:
|
||||||
contents = codecs.open(path, 'r', encoding = enc).read()
|
contents = codecs.open(path, 'r', encoding = enc).read()
|
||||||
app.logger.debug('Read file {} with {} encoding'.format(path, enc))
|
current_app.logger.debug('Read file {} with {} encoding'.format(path, enc))
|
||||||
# Maybe save the encoding somewhere to prevent going through this loop each time for the same file
|
# Maybe save the encoding somewhere to prevent going through this loop each time for the same file
|
||||||
return contents
|
return contents
|
||||||
except UnicodeError:
|
except UnicodeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Fallback to ASCII
|
# Fallback to ASCII
|
||||||
app.logger.debug('Reading file {} with ascii encoding'.format(path))
|
current_app.logger.debug('Reading file {} with ascii encoding'.format(path))
|
||||||
return unicode(open(path, 'r').read())
|
return unicode(open(path, 'r').read())
|
||||||
|
|
||||||
|
@ -20,16 +20,16 @@
|
|||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from flask import request, current_app as app
|
from flask import request
|
||||||
from pony.orm import db_session, rollback
|
from pony.orm import db_session, rollback
|
||||||
from pony.orm import ObjectNotFound
|
from pony.orm import ObjectNotFound
|
||||||
|
|
||||||
from ..db import Playlist, User, Track
|
from ..db import Playlist, User, Track
|
||||||
from ..py23 import dict
|
from ..py23 import dict
|
||||||
|
|
||||||
from . import get_entity
|
from . import api, get_entity
|
||||||
|
|
||||||
@app.route('/rest/getPlaylists.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getPlaylists.view', methods = [ 'GET', 'POST' ])
|
||||||
def list_playlists():
|
def list_playlists():
|
||||||
query = Playlist.select(lambda p: p.user.id == request.user.id or p.public).order_by(Playlist.name)
|
query = Playlist.select(lambda p: p.user.id == request.user.id or p.public).order_by(Playlist.name)
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ def list_playlists():
|
|||||||
with db_session:
|
with db_session:
|
||||||
return request.formatter(dict(playlists = dict(playlist = [ p.as_subsonic_playlist(request.user) for p in query ] )))
|
return request.formatter(dict(playlists = dict(playlist = [ p.as_subsonic_playlist(request.user) for p in query ] )))
|
||||||
|
|
||||||
@app.route('/rest/getPlaylist.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getPlaylist.view', methods = [ 'GET', 'POST' ])
|
||||||
@db_session
|
@db_session
|
||||||
def show_playlist():
|
def show_playlist():
|
||||||
status, res = get_entity(request, Playlist)
|
status, res = get_entity(request, Playlist)
|
||||||
@ -62,7 +62,7 @@ def show_playlist():
|
|||||||
info['entry'] = [ t.as_subsonic_child(request.user, request.client) for t in res.get_tracks() ]
|
info['entry'] = [ t.as_subsonic_child(request.user, request.client) for t in res.get_tracks() ]
|
||||||
return request.formatter(dict(playlist = info))
|
return request.formatter(dict(playlist = info))
|
||||||
|
|
||||||
@app.route('/rest/createPlaylist.view', methods = [ 'GET', 'POST' ])
|
@api.route('/createPlaylist.view', methods = [ 'GET', 'POST' ])
|
||||||
@db_session
|
@db_session
|
||||||
def create_playlist():
|
def create_playlist():
|
||||||
playlist_id, name = map(request.values.get, [ 'playlistId', 'name' ])
|
playlist_id, name = map(request.values.get, [ 'playlistId', 'name' ])
|
||||||
@ -104,7 +104,7 @@ def create_playlist():
|
|||||||
|
|
||||||
return request.formatter(dict())
|
return request.formatter(dict())
|
||||||
|
|
||||||
@app.route('/rest/deletePlaylist.view', methods = [ 'GET', 'POST' ])
|
@api.route('/deletePlaylist.view', methods = [ 'GET', 'POST' ])
|
||||||
@db_session
|
@db_session
|
||||||
def delete_playlist():
|
def delete_playlist():
|
||||||
status, res = get_entity(request, Playlist)
|
status, res = get_entity(request, Playlist)
|
||||||
@ -117,7 +117,7 @@ def delete_playlist():
|
|||||||
res.delete()
|
res.delete()
|
||||||
return request.formatter(dict())
|
return request.formatter(dict())
|
||||||
|
|
||||||
@app.route('/rest/updatePlaylist.view', methods = [ 'GET', 'POST' ])
|
@api.route('/updatePlaylist.view', methods = [ 'GET', 'POST' ])
|
||||||
@db_session
|
@db_session
|
||||||
def update_playlist():
|
def update_playlist():
|
||||||
status, res = get_entity(request, Playlist, 'playlistId')
|
status, res = get_entity(request, Playlist, 'playlistId')
|
||||||
|
@ -20,13 +20,14 @@
|
|||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from flask import request, current_app as app
|
from flask import request
|
||||||
from pony.orm import db_session, select
|
from pony.orm import db_session, select
|
||||||
|
|
||||||
from ..db import Folder, Track, Artist, Album
|
from ..db import Folder, Track, Artist, Album
|
||||||
from ..py23 import dict
|
from ..py23 import dict
|
||||||
|
from . import api
|
||||||
|
|
||||||
@app.route('/rest/search.view', methods = [ 'GET', 'POST' ])
|
@api.route('/search.view', methods = [ 'GET', 'POST' ])
|
||||||
def old_search():
|
def old_search():
|
||||||
artist, album, title, anyf, count, offset, newer_than = map(request.values.get, [ 'artist', 'album', 'title', 'any', 'count', 'offset', 'newerThan' ])
|
artist, album, title, anyf, count, offset, newer_than = map(request.values.get, [ 'artist', 'album', 'title', 'any', 'count', 'offset', 'newerThan' ])
|
||||||
try:
|
try:
|
||||||
@ -70,7 +71,7 @@ def old_search():
|
|||||||
match = [ r.as_subsonic_child(request.user) if isinstance(r, Folder) else r.as_subsonic_child(request.user, request.client) for r in query[offset : offset + count] ]
|
match = [ r.as_subsonic_child(request.user) if isinstance(r, Folder) else r.as_subsonic_child(request.user, request.client) for r in query[offset : offset + count] ]
|
||||||
)))
|
)))
|
||||||
|
|
||||||
@app.route('/rest/search2.view', methods = [ 'GET', 'POST' ])
|
@api.route('/search2.view', methods = [ 'GET', 'POST' ])
|
||||||
def new_search():
|
def new_search():
|
||||||
query, artist_count, artist_offset, album_count, album_offset, song_count, song_offset = map(
|
query, artist_count, artist_offset, album_count, album_offset, song_count, song_offset = map(
|
||||||
request.values.get, [ 'query', 'artistCount', 'artistOffset', 'albumCount', 'albumOffset', 'songCount', 'songOffset' ])
|
request.values.get, [ 'query', 'artistCount', 'artistOffset', 'albumCount', 'albumOffset', 'songCount', 'songOffset' ])
|
||||||
@ -99,7 +100,7 @@ def new_search():
|
|||||||
('song', [ t.as_subsonic_child(request.user, request.client) for t in songs ])
|
('song', [ t.as_subsonic_child(request.user, request.client) for t in songs ])
|
||||||
))))
|
))))
|
||||||
|
|
||||||
@app.route('/rest/search3.view', methods = [ 'GET', 'POST' ])
|
@api.route('/search3.view', methods = [ 'GET', 'POST' ])
|
||||||
def search_id3():
|
def search_id3():
|
||||||
query, artist_count, artist_offset, album_count, album_offset, song_count, song_offset = map(
|
query, artist_count, artist_offset, album_count, album_offset, song_count, song_offset = map(
|
||||||
request.values.get, [ 'query', 'artistCount', 'artistOffset', 'albumCount', 'albumOffset', 'songCount', 'songOffset' ])
|
request.values.get, [ 'query', 'artistCount', 'artistOffset', 'albumCount', 'albumOffset', 'songCount', 'songOffset' ])
|
||||||
|
@ -18,15 +18,16 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from flask import request, current_app as app
|
from flask import request
|
||||||
|
|
||||||
from ..py23 import dict
|
from ..py23 import dict
|
||||||
|
from . import api
|
||||||
|
|
||||||
@app.route('/rest/ping.view', methods = [ 'GET', 'POST' ])
|
@api.route('/ping.view', methods = [ 'GET', 'POST' ])
|
||||||
def ping():
|
def ping():
|
||||||
return request.formatter(dict())
|
return request.formatter(dict())
|
||||||
|
|
||||||
@app.route('/rest/getLicense.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getLicense.view', methods = [ 'GET', 'POST' ])
|
||||||
def license():
|
def license():
|
||||||
return request.formatter(dict(license = dict(valid = True )))
|
return request.formatter(dict(license = dict(valid = True )))
|
||||||
|
|
||||||
|
@ -18,16 +18,16 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from flask import request, current_app as app
|
from flask import request
|
||||||
from pony.orm import db_session
|
from pony.orm import db_session
|
||||||
|
|
||||||
from ..db import User
|
from ..db import User
|
||||||
from ..managers.user import UserManager
|
from ..managers.user import UserManager
|
||||||
from ..py23 import dict
|
from ..py23 import dict
|
||||||
|
|
||||||
from . import decode_password
|
from . import api, decode_password
|
||||||
|
|
||||||
@app.route('/rest/getUser.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getUser.view', methods = [ 'GET', 'POST' ])
|
||||||
def user_info():
|
def user_info():
|
||||||
username = request.values.get('username')
|
username = request.values.get('username')
|
||||||
if username is None:
|
if username is None:
|
||||||
@ -43,7 +43,7 @@ def user_info():
|
|||||||
|
|
||||||
return request.formatter(dict(user = user.as_subsonic_user()))
|
return request.formatter(dict(user = user.as_subsonic_user()))
|
||||||
|
|
||||||
@app.route('/rest/getUsers.view', methods = [ 'GET', 'POST' ])
|
@api.route('/getUsers.view', methods = [ 'GET', 'POST' ])
|
||||||
def users_info():
|
def users_info():
|
||||||
if not request.user.admin:
|
if not request.user.admin:
|
||||||
return request.error_formatter(50, 'Admin restricted')
|
return request.error_formatter(50, 'Admin restricted')
|
||||||
@ -51,7 +51,7 @@ def users_info():
|
|||||||
with db_session:
|
with db_session:
|
||||||
return request.formatter(dict(users = dict(user = [ u.as_subsonic_user() for u in User.select() ] )))
|
return request.formatter(dict(users = dict(user = [ u.as_subsonic_user() for u in User.select() ] )))
|
||||||
|
|
||||||
@app.route('/rest/createUser.view', methods = [ 'GET', 'POST' ])
|
@api.route('/createUser.view', methods = [ 'GET', 'POST' ])
|
||||||
def user_add():
|
def user_add():
|
||||||
if not request.user.admin:
|
if not request.user.admin:
|
||||||
return request.error_formatter(50, 'Admin restricted')
|
return request.error_formatter(50, 'Admin restricted')
|
||||||
@ -68,7 +68,7 @@ def user_add():
|
|||||||
|
|
||||||
return request.formatter(dict())
|
return request.formatter(dict())
|
||||||
|
|
||||||
@app.route('/rest/deleteUser.view', methods = [ 'GET', 'POST' ])
|
@api.route('/deleteUser.view', methods = [ 'GET', 'POST' ])
|
||||||
def user_del():
|
def user_del():
|
||||||
if not request.user.admin:
|
if not request.user.admin:
|
||||||
return request.error_formatter(50, 'Admin restricted')
|
return request.error_formatter(50, 'Admin restricted')
|
||||||
@ -88,7 +88,7 @@ def user_del():
|
|||||||
|
|
||||||
return request.formatter(dict())
|
return request.formatter(dict())
|
||||||
|
|
||||||
@app.route('/rest/changePassword.view', methods = [ 'GET', 'POST' ])
|
@api.route('/changePassword.view', methods = [ 'GET', 'POST' ])
|
||||||
def user_changepass():
|
def user_changepass():
|
||||||
username, password = map(request.values.get, [ 'username', 'password' ])
|
username, password = map(request.values.get, [ 'username', 'password' ])
|
||||||
if not username or not password:
|
if not username or not password:
|
||||||
|
@ -65,7 +65,8 @@ def create_application(config = None):
|
|||||||
if app.config['WEBAPP']['mount_webui']:
|
if app.config['WEBAPP']['mount_webui']:
|
||||||
from . import frontend
|
from . import frontend
|
||||||
if app.config['WEBAPP']['mount_api']:
|
if app.config['WEBAPP']['mount_api']:
|
||||||
from . import api
|
from .api import api
|
||||||
|
app.register_blueprint(api, url_prefix = '/rest')
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user