1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-12-22 17:06:17 +00:00

Get on my pony

This commit is contained in:
spl0k 2017-12-21 23:29:00 +01:00
parent 6daedc6919
commit 53fd4865cb
13 changed files with 115 additions and 125 deletions

View File

@ -18,15 +18,15 @@
# 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/>.
import binascii
import simplejson
import uuid
import binascii
from flask import request, current_app as app
from pony.orm import db_session, ObjectNotFound
from xml.dom import minidom
from xml.etree import ElementTree
from ..web import store
from ..managers.user import UserManager
@app.before_request
@ -70,7 +70,7 @@ def authorize():
error = request.error_formatter(40, 'Unauthorized'), 401
if request.authorization:
status, user = UserManager.try_auth(store, request.authorization.username, request.authorization.password)
status, user = UserManager.try_auth(request.authorization.username, request.authorization.password)
if status == UserManager.SUCCESS:
request.username = request.authorization.username
request.user = user
@ -81,7 +81,7 @@ def authorize():
return error
password = decode_password(password)
status, user = UserManager.try_auth(store, username, password)
status, user = UserManager.try_auth(username, password)
if status != UserManager.SUCCESS:
return error
@ -97,13 +97,11 @@ def get_client_prefs():
return request.error_formatter(10, 'Missing required parameter')
client = request.values.get('c')
prefs = store.get(ClientPrefs, (request.user.id, client))
if not prefs:
prefs = ClientPrefs()
prefs.user_id = request.user.id
prefs.client_name = client
store.add(prefs)
store.commit()
with db_session:
try:
prefs = ClientPrefs[request.user.id, client]
except ObjectNotFound:
prefs = ClientPrefs(user = User[request.user.id], client_name = client)
request.prefs = prefs

View File

@ -23,12 +23,9 @@ import uuid
from datetime import timedelta
from flask import request, current_app as app
from storm.expr import Desc, Avg, Min, Max
from storm.info import ClassAlias
from ..db import Folder, Artist, Album, Track, RatingFolder, StarredFolder, StarredArtist, StarredAlbum, StarredTrack, User
from ..db import now
from ..web import store
@app.route('/rest/getRandomSongs.view', methods = [ 'GET', 'POST' ])
def rand_songs():

View File

@ -27,7 +27,6 @@ from ..db import Track, Album, Artist, Folder
from ..db import StarredTrack, StarredAlbum, StarredArtist, StarredFolder
from ..db import RatingTrack, RatingFolder
from ..lastfm import LastFm
from ..web import store
from . import get_entity

View File

@ -24,7 +24,6 @@ import uuid
from flask import request, current_app as app
from ..db import Folder, Artist, Album, Track
from ..web import store
from . import get_entity

View File

@ -19,9 +19,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from flask import request, current_app as app
from pony.orm import db_session
from ..db import ChatMessage
from ..web import store
from ..db import ChatMessage, User
@app.route('/rest/getChatMessages.view', methods = [ 'GET', 'POST' ])
def get_chat():
@ -31,11 +31,12 @@ def get_chat():
except:
return request.error_formatter(0, 'Invalid parameter')
query = store.find(ChatMessage).order_by(ChatMessage.time)
if since:
query = query.find(ChatMessage.time > since)
with db_session:
query = ChatMessage.select().order_by(ChatMessage.time)
if since:
query = query.filter(lambda m: m.time > since)
return request.formatter({ 'chatMessages': { 'chatMessage': [ msg.responsize() for msg in query ] }})
return request.formatter({ 'chatMessages': { 'chatMessage': [ msg.responsize() for msg in query ] }})
@app.route('/rest/addChatMessage.view', methods = [ 'GET', 'POST' ])
def add_chat_message():
@ -43,10 +44,8 @@ def add_chat_message():
if not msg:
return request.error_formatter(10, 'Missing message')
chat = ChatMessage()
chat.user_id = request.user.id
chat.message = msg
store.add(chat)
store.commit()
with db_session:
ChatMessage(user = User[request.user.id], message = msg)
return request.formatter({})

View File

@ -29,7 +29,6 @@ from PIL import Image
from xml.etree import ElementTree
from .. import scanner
from ..web import store
from ..db import Track, Album, Artist, Folder, User, ClientPrefs, now
from . import get_entity

View File

@ -21,10 +21,8 @@
import uuid
from flask import request, current_app as app
from storm.expr import Or
from ..db import Playlist, User, Track
from ..web import store
from . import get_entity

View File

@ -20,10 +20,9 @@
from datetime import datetime
from flask import request, current_app as app
from storm.info import ClassAlias
from pony.orm import db_session, select
from ..db import Folder, Track, Artist, Album
from ..web import store
@app.route('/rest/search.view', methods = [ 'GET', 'POST' ])
def old_search():
@ -38,34 +37,36 @@ def old_search():
min_date = datetime.fromtimestamp(newer_than)
if artist:
parent = ClassAlias(Folder)
query = store.find(parent, Folder.parent_id == parent.id, Track.folder_id == Folder.id, parent.name.contains_string(artist), parent.created > min_date).config(distinct = True)
query = select(t.folder.parent for t in Track if artist in t.folder.parent.name and t.folder.parent.created > min_date)
elif album:
query = store.find(Folder, Track.folder_id == Folder.id, Folder.name.contains_string(album), Folder.created > min_date).config(distinct = True)
query = select(t.folder for t in Track if album in t.folder.name and t.folder.created > min_date)
elif title:
query = store.find(Track, Track.title.contains_string(title), Track.created > min_date)
query = Track.select(lambda t: title in t.title and t.created > min_date)
elif anyf:
folders = store.find(Folder, Folder.name.contains_string(anyf), Folder.created > min_date)
tracks = store.find(Track, Track.title.contains_string(anyf), Track.created > min_date)
res = list(folders[offset : offset + count])
if offset + count > folders.count():
toff = max(0, offset - folders.count())
tend = offset + count - folders.count()
res += list(tracks[toff : tend])
folders = Folder.select(lambda f: anyf in f.name and f.created > min_date)
tracks = Track.select(lambda t: anyf in t.title and t.created > min_date)
with db_session:
res = folders[offset : offset + count]
fcount = folders.count()
if offset + count > fcount:
toff = max(0, offset - fcount)
tend = offset + count - fcount
res += tracks[toff : tend]
return request.formatter({ 'searchResult': {
'totalHits': folders.count() + tracks.count(),
'offset': offset,
'match': [ r.as_subsonic_child(request.user) if isinstance(r, Folder) else r.as_subsonic_child(request.user, request.prefs) for r in res ]
}})
return request.formatter({ 'searchResult': {
'totalHits': folders.count() + tracks.count(),
'offset': offset,
'match': [ r.as_subsonic_child(request.user) if isinstance(r, Folder) else r.as_subsonic_child(request.user, request.prefs) for r in res ]
}})
else:
return request.error_formatter(10, 'Missing search parameter')
return request.formatter({ 'searchResult': {
'totalHits': query.count(),
'offset': offset,
'match': [ r.as_subsonic_child(request.user) if isinstance(r, Folder) else r.as_subsonic_child(request.user, request.prefs) for r in query[offset : offset + count] ]
}})
with db_session:
return request.formatter({ 'searchResult': {
'totalHits': query.count(),
'offset': offset,
'match': [ r.as_subsonic_child(request.user) if isinstance(r, Folder) else r.as_subsonic_child(request.user, request.prefs) for r in query[offset : offset + count] ]
}})
@app.route('/rest/search2.view', methods = [ 'GET', 'POST' ])
def new_search():
@ -85,16 +86,16 @@ def new_search():
if not query:
return request.error_formatter(10, 'Missing query parameter')
parent = ClassAlias(Folder)
artist_query = store.find(parent, Folder.parent_id == parent.id, Track.folder_id == Folder.id, parent.name.contains_string(query)).config(distinct = True, offset = artist_offset, limit = artist_count)
album_query = store.find(Folder, Track.folder_id == Folder.id, Folder.name.contains_string(query)).config(distinct = True, offset = album_offset, limit = album_count)
song_query = store.find(Track, Track.title.contains_string(query))[song_offset : song_offset + song_count]
with db_session:
artists = select(t.folder.parent for t in Track if query in t.folder.parent.name).limit(artist_count, artist_offset)
albums = select(t.folder for t in Track if query in t.folder.name).limit(album_count, album_offset)
songs = Track.select(lambda t: query in t.title).limit(song_count, song_offset)
return request.formatter({ 'searchResult2': {
'artist': [ { 'id': str(a.id), 'name': a.name } for a in artist_query ],
'album': [ f.as_subsonic_child(request.user) for f in album_query ],
'song': [ t.as_subsonic_child(request.user, request.prefs) for t in song_query ]
}})
return request.formatter({ 'searchResult2': {
'artist': [ { 'id': str(a.id), 'name': a.name } for a in artists ],
'album': [ f.as_subsonic_child(request.user) for f in albums ],
'song': [ t.as_subsonic_child(request.user, request.prefs) for t in songs ]
}})
@app.route('/rest/search3.view', methods = [ 'GET', 'POST' ])
def search_id3():
@ -114,13 +115,14 @@ def search_id3():
if not query:
return request.error_formatter(10, 'Missing query parameter')
artist_query = store.find(Artist, Artist.name.contains_string(query))[artist_offset : artist_offset + artist_count]
album_query = store.find(Album, Album.name.contains_string(query))[album_offset : album_offset + album_count]
song_query = store.find(Track, Track.title.contains_string(query))[song_offset : song_offset + song_count]
with db_session:
artists = Artist.select(lambda a: query in a.name).limit(artist_count, artist_offset)
albums = Album.select(lambda a: query in a.name).limit(album_count, album_offset)
songs = Track.select(lambda t: query in t.title).limit(song_count, song_offset)
return request.formatter({ 'searchResult3': {
'artist': [ a.as_subsonic_artist(request.user) for a in artist_query ],
'album': [ a.as_subsonic_album(request.user) for a in album_query ],
'song': [ t.as_subsonic_child(request.user, request.prefs) for t in song_query ]
}})
return request.formatter({ 'searchResult3': {
'artist': [ a.as_subsonic_artist(request.user) for a in artists ],
'album': [ a.as_subsonic_album(request.user) for a in albums ],
'song': [ t.as_subsonic_child(request.user, request.prefs) for t in songs ]
}})

View File

@ -19,10 +19,10 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from flask import request, current_app as app
from pony.orm import db_session
from ..db import User
from ..managers.user import UserManager
from ..web import store
from . import decode_password
@ -35,7 +35,8 @@ def user_info():
if username != request.username and not request.user.admin:
return request.error_formatter(50, 'Admin restricted')
user = store.find(User, User.name == username).one()
with db_session:
user = User.get(name = username)
if user is None:
return request.error_formatter(70, 'Unknown user')
@ -46,7 +47,8 @@ def users_info():
if not request.user.admin:
return request.error_formatter(50, 'Admin restricted')
return request.formatter({ 'users': { 'user': [ u.as_subsonic_user() for u in store.find(User) ] } })
with db_session:
return request.formatter({ 'users': { 'user': [ u.as_subsonic_user() for u in User.select() ] } })
@app.route('/rest/createUser.view', methods = [ 'GET', 'POST' ])
def user_add():
@ -59,7 +61,7 @@ def user_add():
admin = True if admin in (True, 'True', 'true', 1, '1') else False
password = decode_password(password)
status = UserManager.add(store, username, password, email, admin)
status = UserManager.add(username, password, email, admin)
if status == UserManager.NAME_EXISTS:
return request.error_formatter(0, 'There is already a user with that username')
@ -74,11 +76,12 @@ def user_del():
if not username:
return request.error_formatter(10, 'Missing parameter')
user = store.find(User, User.name == username).one()
if not user:
with db_session:
user = User.get(name = username)
if user is None:
return request.error_formatter(70, 'Unknown user')
status = UserManager.delete(store, user.id)
status = UserManager.delete(user.id)
if status != UserManager.SUCCESS:
return request.error_formatter(0, UserManager.error_str(status))
@ -94,7 +97,7 @@ def user_changepass():
return request.error_formatter(50, 'Admin restricted')
password = decode_password(password)
status = UserManager.change_password2(store, username, password)
status = UserManager.change_password2(username, password)
if status != UserManager.SUCCESS:
code = 0
if status == UserManager.NO_SUCH_USER:

View File

@ -130,8 +130,8 @@ class Album(db.Entity):
'created': min(self.tracks.created).isoformat()
}
track_with_cover = self.tracks.select(lambda t: t.folder.has_cover_art)[:1][0]
if track_with_cover:
track_with_cover = self.tracks.select(lambda t: t.folder.has_cover_art).first()
if track_with_cover is not None:
info['coverArt'] = str(track_with_cover.folder.id)
try:

View File

@ -11,7 +11,10 @@
import unittest
from . import base, managers, api, frontend
from . import base
from . import managers
from . import api
from . import frontend
def suite():
suite = unittest.TestSuite()

View File

@ -12,6 +12,8 @@
import time
import unittest
from pony.orm import db_session, commit
from supysonic.db import Folder, Artist, Album, Track
from .apitestbase import ApiTestBase
@ -20,53 +22,44 @@ class SearchTestCase(ApiTestBase):
def setUp(self):
super(SearchTestCase, self).setUp()
root = Folder()
root.root = True
root.name = 'Root folder'
root.path = 'tests/assets'
self.store.add(root)
with db_session:
root = Folder(root = True, name = 'Root folder', path = 'tests/assets')
for letter in 'ABC':
folder = Folder()
folder.name = letter + 'rtist'
folder.path = 'tests/assets/{}rtist'.format(letter)
folder.parent = root
for letter in 'ABC':
folder = Folder(name = letter + 'rtist', path = 'tests/assets/{}rtist'.format(letter), parent = root)
artist = Artist(name = letter + 'rtist')
artist = Artist()
artist.name = letter + 'rtist'
for lether in 'AB':
afolder = Folder(
name = letter + lether + 'lbum',
path = 'tests/assets/{0}rtist/{0}{1}lbum'.format(letter, lether),
parent = folder
)
for lether in 'AB':
afolder = Folder()
afolder.name = letter + lether + 'lbum'
afolder.path = 'tests/assets/{0}rtist/{0}{1}lbum'.format(letter, lether)
afolder.parent = folder
album = Album(name = letter + lether + 'lbum', artist = artist)
album = Album()
album.name = letter + lether + 'lbum'
album.artist = artist
for num, song in enumerate([ 'One', 'Two', 'Three' ]):
track = Track(
disc = 1,
number = num,
title = song,
duration = 2,
album = album,
artist = artist,
bitrate = 320,
path = 'tests/assets/{0}rtist/{0}{1}lbum/{2}'.format(letter, lether, song),
content_type = 'audio/mpeg',
last_modification = 0,
root_folder = root,
folder = afolder
)
for num, song in enumerate([ 'One', 'Two', 'Three' ]):
track = Track()
track.disc = 1
track.number = num
track.title = song
track.duration = 2
track.album = album
track.artist = artist
track.bitrate = 320
track.path = 'tests/assets/{0}rtist/{0}{1}lbum/{2}'.format(letter, lether, song)
track.content_type = 'audio/mpeg'
track.last_modification = 0
track.root_folder = root
track.folder = afolder
self.store.add(track)
commit()
self.store.commit()
self.assertEqual(self.store.find(Folder).count(), 10)
self.assertEqual(self.store.find(Artist).count(), 3)
self.assertEqual(self.store.find(Album).count(), 6)
self.assertEqual(self.store.find(Track).count(), 18)
self.assertEqual(Folder.select().count(), 10)
self.assertEqual(Artist.select().count(), 3)
self.assertEqual(Album.select().count(), 6)
self.assertEqual(Track.select().count(), 18)
def __track_as_pseudo_unique_str(self, elem):
return elem.get('artist') + elem.get('album') + elem.get('title')

View File

@ -68,8 +68,8 @@ class TestBase(unittest.TestCase):
release_database()
app = create_application(config)
#self.__ctx = app.app_context()
#self.__ctx.push()
self.__ctx = app.app_context()
self.__ctx.push()
self.client = app.test_client()
@ -83,7 +83,7 @@ class TestBase(unittest.TestCase):
return False
def tearDown(self):
#self.__ctx.pop()
self.__ctx.pop()
release_database()
shutil.rmtree(self.__dir)
os.remove(self.__dbfile)