Exemple #1
0
def new_search():
	query, artist_count, artist_offset, album_count, album_offset, song_count, song_offset = map(
		request.args.get, [ 'query', 'artistCount', 'artistOffset', 'albumCount', 'albumOffset', 'songCount', 'songOffset' ])

	try:
		artist_count =  int(artist_count)  if artist_count  else 20
		artist_offset = int(artist_offset) if artist_offset else 0
		album_count =   int(album_count)   if album_count   else 20
		album_offset =  int(album_offset)  if album_offset  else 0
		song_count =    int(song_count)    if song_count    else 20
		song_offset =   int(song_offset)   if song_offset   else 0
	except:
		return request.error_formatter(0, 'Invalid parameter')

	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]

	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) for t in song_query ]
	}})
Exemple #2
0
def search_id3():
    query, artist_count, artist_offset, album_count, album_offset, song_count, song_offset = map(
        request.values.get, [ 'query', 'artistCount', 'artistOffset', 'albumCount', 'albumOffset', 'songCount', 'songOffset' ])

    try:
        artist_count =  int(artist_count)  if artist_count  else 20
        artist_offset = int(artist_offset) if artist_offset else 0
        album_count =   int(album_count)   if album_count   else 20
        album_offset =  int(album_offset)  if album_offset  else 0
        song_count =    int(song_count)    if song_count    else 20
        song_offset =   int(song_offset)   if song_offset   else 0
    except:
        return request.error_formatter(0, 'Invalid parameter')

    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]

    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 ]
    }})
Exemple #3
0
def search_id3():
	query, artist_count, artist_offset, album_count, album_offset, song_count, song_offset = map(
			request.args.get, [ 'query', 'artistCount', 'artistOffset', 'albumCount', 'albumOffset', 'songCount', 'songOffset' ])

	try:
		artist_count = int(artist_count) if artist_count else 20
		artist_offset = int(artist_offset) if artist_offset else 0
		album_count = int(album_count) if album_count else 20
		album_offset = int(album_offset) if album_offset else 0
		song_count = int(song_count) if song_count else 20
		song_offset = int(song_offset) if song_offset else 0
	except:
		return request.error_formatter(0, 'Invalid parameter')

	if not query:
		return request.error_formatter(10, 'Missing query parameter')

	artist_query = session.query(Artist).filter(Artist.name.contains(query)).slice(artist_offset, artist_offset + artist_count)
	album_query = session.query(Album).filter(Album.name.contains(query)).slice(album_offset, album_offset + album_count)
	song_query = session.query(Track).filter(Track.title.contains(query)).slice(song_offset, song_offset + song_count)

	return request.formatter({ 'searchResult2': {
		'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) for t in song_query ]
		}})
Exemple #4
0
def cover_art():
	status, res = get_entity(request, Folder)
	if not status:
		return res

	if not res.has_cover_art or not os.path.isfile(os.path.join(res.path, 'cover.jpg')):
		return request.error_formatter(70, 'Cover art not found')

	size = request.values.get('size')
	if size:
		try:
			size = int(size)
		except:
			return request.error_formatter(0, 'Invalid size value')
	else:
		return send_file(os.path.join(res.path, 'cover.jpg'))

	im = Image.open(os.path.join(res.path, 'cover.jpg'))
	if size > im.size[0] and size > im.size[1]:
		return send_file(os.path.join(res.path, 'cover.jpg'))

	size_path = os.path.join(config.get('webapp', 'cache_dir'), str(size))
	path = os.path.join(size_path, str(res.id))
	if os.path.exists(path):
		return send_file(path)
	if not os.path.exists(size_path):
		os.makedirs(size_path)

	im.thumbnail([size, size], Image.ANTIALIAS)
	im.save(path, 'JPEG')
	return send_file(path)
Exemple #5
0
def new_search():
	query, artist_count, artist_offset, album_count, album_offset, song_count, song_offset = map(
	request.args.get, [ 'query', 'artistCount', 'artistOffset', 'albumCount', 'albumOffset', 'songCount', 'songOffset' ])

	try:
		artist_count = int(artist_count) if artist_count else 20
		artist_offset = int(artist_offset) if artist_offset else 0
		album_count = int(album_count) if album_count else 20
		album_offset = int(album_offset) if album_offset else 0
		song_count = int(song_count) if song_count else 20
		song_offset = int(song_offset) if song_offset else 0
	except:
		return request.error_formatter(0, 'Invalid parameter')

	if not query:
		return request.error_formatter(10, 'Missing query parameter')

	artist_query = session.query(Folder).filter(~ Folder.tracks.any(), Folder.path.contains(query)).slice(artist_offset, artist_offset + artist_count)
	album_query = session.query(Folder).filter(Folder.tracks.any(), Folder.path.contains(query)).slice(album_offset, album_offset + album_count)
	song_query = sesion.query(Track).filter(Track.title.contains(query)).slice(song_offset, song_offset + song_count)

	return request.formatter({ 'searchResult2': {
		'artist': [ { 'id': 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) for t in song_query ]
	}})
Exemple #6
0
def cover_art():
    status, res = get_entity(request, Folder)
    if not status:
        return res

    if not res.has_cover_art or not os.path.isfile(
            os.path.join(res.path, 'cover.jpg')):
        return request.error_formatter(70, 'Cover art not found')

    size = request.values.get('size')
    if size:
        try:
            size = int(size)
        except:
            return request.error_formatter(0, 'Invalid size value')
    else:
        return send_file(os.path.join(res.path, 'cover.jpg'))

    im = Image.open(os.path.join(res.path, 'cover.jpg'))
    if size > im.size[0] and size > im.size[1]:
        return send_file(os.path.join(res.path, 'cover.jpg'))

    size_path = os.path.join(app.config['WEBAPP']['cache_dir'], str(size))
    path = os.path.abspath(os.path.join(size_path, str(res.id)))
    if os.path.exists(path):
        return send_file(path, mimetype='image/jpeg')
    if not os.path.exists(size_path):
        os.makedirs(size_path)

    im.thumbnail([size, size], Image.ANTIALIAS)
    im.save(path, 'JPEG')
    return send_file(path, mimetype='image/jpeg')
Exemple #7
0
def rate():
	id, rating = map(request.args.get, [ 'id', 'rating' ])
	if not id or not rating:
		return request.error_formatter(10, 'Missing parameter')

	try:
		uid = uuid.UUID(id)
		rating = int(rating)
	except:
		return request.error_formatter(0, 'Invalid parameter')

	if not rating in xrange(6):
		return request.error_formatter(0, 'rating must be between 0 and 5 (inclusive)')

	if rating == 0:
		RatingTrack.query.filter(RatingTrack.user_id == request.user.id).filter(RatingTrack.rated_id == uid).delete()
		RatingFolder.query.filter(RatingFolder.user_id == request.user.id).filter(RatingFolder.rated_id == uid).delete()
	else:
		rated = Track.query.get(uid)
		rating_ent = RatingTrack
		if not rated:
			rated = Folder.query.get(uid)
			rating_ent = RatingFolder
			if not rated:
				return request.error_formatter(70, 'Unknown id')

		rating_info = rating_ent.query.get((request.user.id, uid))
		if rating_info:
			rating_info.rating = rating
		else:
			session.add(rating_ent(user = request.user, rated = rated, rating = rating))

	session.commit()
	return request.formatter({})
Exemple #8
0
def new_search():
	query, artist_count, artist_offset, album_count, album_offset, song_count, song_offset = map(
		request.args.get, [ 'query', 'artistCount', 'artistOffset', 'albumCount', 'albumOffset', 'songCount', 'songOffset' ])

	try:
		artist_count = int(artist_count) if artist_count else 20
		artist_offset = int(artist_offset) if artist_offset else 0
		album_count = int(album_count) if album_count else 20
		album_offset = int(album_offset) if album_offset else 0
		song_count = int(song_count) if song_count else 20
		song_offset = int(song_offset) if song_offset else 0
	except:
		return request.error_formatter(0, 'Invalid parameter')

	if not query:
		return request.error_formatter(10, 'Missing query parameter')

	artist_query = Folder.query.filter(~ Folder.tracks.any(), Folder.name.contains(query)).slice(artist_offset, artist_offset + artist_count)
	album_query = Folder.query.filter(Folder.tracks.any(), Folder.name.contains(query)).slice(album_offset, album_offset + album_count)
	song_query = Track.query.filter(Track.title.contains(query)).slice(song_offset, song_offset + song_count)

	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) for t in song_query ]
	}})
Exemple #9
0
def cover_art():
	# Use the track id to get the file path.
	# TODO: support for multiple query types is a matter of a few case statements
	status, res = get_entity(request, Track)
	if not status:
		return res

	res = res.folder

	if not res.has_cover_art or not os.path.isfile(os.path.join(res.path, 'cover.jpg')):
		return request.error_formatter(70, 'Cover art not found')

	size = request.args.get('size')
	if size:
		try:
			size = int(size)
		except:
			return request.error_formatter(0, 'Invalid size value')
	else:
		return send_file(os.path.join(res.path, 'cover.jpg'))

	im = Image.open(os.path.join(res.path, 'cover.jpg'))
	if size > im.size[0] and size > im.size[1]:
		return send_file(os.path.join(res.path, 'cover.jpg'))

	size_path = os.path.join(config.get('base', 'cache_dir'), str(size))
	path = os.path.join(size_path, str(res.id))
	if os.path.exists(path):
		return send_file(path)
	if not os.path.exists(size_path):
		os.makedirs(size_path)

	im.thumbnail([size, size], Image.ANTIALIAS)
	im.save(path, 'JPEG')
	return send_file(path, mimetype='image/jpeg;base64')
Exemple #10
0
def search_id3():
	query, artist_count, artist_offset, album_count, album_offset, song_count, song_offset = map(
		request.args.get, [ 'query', 'artistCount', 'artistOffset', 'albumCount', 'albumOffset', 'songCount', 'songOffset' ])

	try:
		artist_count = int(artist_count) if artist_count else 20
		artist_offset = int(artist_offset) if artist_offset else 0
		album_count = int(album_count) if album_count else 20
		album_offset = int(album_offset) if album_offset else 0
		song_count = int(song_count) if song_count else 20
		song_offset = int(song_offset) if song_offset else 0
	except:
		return request.error_formatter(0, 'Invalid parameter')

	if not query:
		return request.error_formatter(10, 'Missing query parameter')

	artist_query = Artist.query.filter(Artist.name.contains(query)).slice(artist_offset, artist_offset + artist_count)
	album_query = Album.query.filter(Album.name.contains(query)).slice(album_offset, album_offset + album_count)
	song_query = Track.query.filter(Track.title.contains(query)).slice(song_offset, song_offset + song_count)

	return request.formatter({ 'searchResult2': {
		'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) for t in song_query ]
	}})
Exemple #11
0
def update_playlist():
    status, res = get_entity(request, Playlist, 'playlistId')
    if not status:
        return res

    if res.user_id != request.user.id and not request.user.admin:
        return request.error_formatter(50, "You're not allowed to delete a playlist that isn't yours")

    playlist = res
    name, comment, public = map(request.values.get, [ 'name', 'comment', 'public' ])
    to_add, to_remove = map(request.values.getlist, [ 'songIdToAdd', 'songIndexToRemove' ])
    try:
        to_add = map(uuid.UUID, to_add)
        to_remove = map(int, to_remove)
    except:
        return request.error_formatter(0, 'Invalid parameter')

    if name:
        playlist.name = name
    if comment:
        playlist.comment = comment
    if public:
        playlist.public = public in (True, 'True', 'true', 1, '1')

    for sid in to_add:
        track = store.get(Track, sid)
        if not track:
            return request.error_formatter(70, 'Unknown song')
        playlist.add(track)

    playlist.remove_at_indexes(to_remove)

    store.commit()
    return request.formatter({})
Exemple #12
0
def album_list():
    ltype, size, offset = map(request.args.get, ['type', 'size', 'offset'])
    try:
        size = int(size) if size else 10
        offset = int(offset) if offset else 0
    except:
        return request.error_formatter(0, 'Invalid parameter format')

    query = session.query(Folder).filter(Folder.tracks.any())
    if ltype == 'random':
        albums = []
        count = query.count()

        if not count:
            return request.formatter({'albumList': {}})

        for _ in xrange(size):
            x = random.choice(xrange(count))
            albums.append(query.offset(x).limit(1).one())

        return request.formatter({
            'albumList': {
                'album': [a.as_subsonic_child(request.user) for a in albums]
            }
        })
    elif ltype == 'newest':
        query = query.order_by(desc(Folder.created))
    elif ltype == 'highest':
        query = query.join(RatingFolder).group_by(Folder.id).order_by(
            desc(func.avg(RatingFolder.rating)))
    elif ltype == 'frequent':
        query = query.join(Track, Folder.tracks).group_by(Folder.id).order_by(
            desc(func.avg(Track.play_count)))
    elif ltype == 'recent':
        query = query.join(Track, Folder.tracks).group_by(Folder.id).order_by(
            desc(func.max(Track.last_play)))
    elif ltype == 'starred':
        query = query.join(StarredFolder).join(User).filter(
            User.name == request.username)
    elif ltype == 'alphabeticalByName':
        query = query.order_by(Folder.name)
    elif ltype == 'alphabeticalByArtist':
        # this is a mess because who knows how your file structure is set up
        # with the database changes it's more difficult to get the parent of a dir
        parent = aliased(Folder)
        query = query.join(parent, Folder.parent).order_by(
            parent.name).order_by(Folder.name)
    else:
        return request.error_formatter(0, 'Unknown search type')

    return request.formatter({
        'albumList': {
            'album': [
                f.as_subsonic_child(request.user)
                for f in query.limit(size).offset(offset)
            ]
        }
    })
Exemple #13
0
def cover_art():
    folder = None
    track = None
    res_id = None
    
    status, cover_art = get_entity(request, CoverArt)
    if not status:        
        return cover_art
    
    if cover_art.is_embedded:
        original_dir = os.path.join(config.get('base', 'cache_dir'), 'original')
        if not os.path.exists(original_dir):
            os.makedirs(original_dir)
            
        cover_art_file = os.path.join(original_dir, str(cover_art.id))
        
        # Have we already extracted the cover art to the temporary
        # directory?  If so, we don't bother to do it again.  Otherwise
        # we have to pull the image out of the track tag data.
        # Future: Not handling multiple cover art images in one
        # track yet... results are unpredictable.
        if not os.path.isfile(cover_art_file):        
            # Extract cover art from tag data and save to file.
            cover_tag = CoverTag(cover_art.path)
            if not cover_tag.data:
                return request.error_formatter(70, 'Cover art not found')
            else:    
                f = file(cover_art_file, 'wb')
                f.write(cover_tag.data)
                f.close()
    else:
        cover_art_file = cover_art.path
        if not os.path.isfile(cover_art_file):
            return request.error_formatter(70, 'Cover art not found')
            
    size = request.args.get('size')
    if size:
        try:
            size = int(size)
        except:
            return request.error_formatter(0, 'Invalid size value')
    else:
        return send_file(cover_art_file)

    im = Image.open(cover_art_file)
    if size > im.size[0] and size > im.size[1]:
        return send_file(cover_art_file)

    size_path = os.path.join(config.get('base', 'cache_dir'), str(size))
    path = os.path.join(size_path, str(cover_art.id))
    if os.path.exists(path):
        return send_file(path)
    if not os.path.exists(size_path):
        os.makedirs(size_path)

    im.thumbnail([size, size], Image.ANTIALIAS)
    im.save(path, 'JPEG')
    return send_file(path)
Exemple #14
0
def album_list():
    ltype, size, offset = map(request.args.get, ['type', 'size', 'offset'])
    try:
        size = int(size) if size else 10
        offset = int(offset) if offset else 0
    except:
        return request.error_formatter(0, 'Invalid parameter format')

    query = store.find(Folder, Track.folder_id == Folder.id)
    if ltype == 'random':
        albums = []
        count = query.count()

        if not count:
            return request.formatter({'albumList': {}})

        for _ in xrange(size):
            x = random.choice(xrange(count))
            albums.append(query[x])

        return request.formatter({
            'albumList': {
                'album': [a.as_subsonic_child(request.user) for a in albums]
            }
        })
    elif ltype == 'newest':
        query = query.order_by(Desc(Folder.created)).config(distinct=True)
    elif ltype == 'highest':
        query = query.find(RatingFolder.rated_id == Folder.id).group_by(
            Folder.id).order_by(Desc(Avg(RatingFolder.rating)))
    elif ltype == 'frequent':
        query = query.group_by(Folder.id).order_by(Desc(Avg(Track.play_count)))
    elif ltype == 'recent':
        query = query.group_by(Folder.id).order_by(Desc(Max(Track.last_play)))
    elif ltype == 'starred':
        query = query.find(StarredFolder.starred_id == Folder.id,
                           User.id == StarredFolder.user_id,
                           User.name == request.username)
    elif ltype == 'alphabeticalByName':
        query = query.order_by(Folder.name).config(distinct=True)
    elif ltype == 'alphabeticalByArtist':
        parent = ClassAlias(Folder)
        query = query.find(Folder.parent_id == parent.id).order_by(
            parent.name, Folder.name).config(distinct=True)
    else:
        return request.error_formatter(0, 'Unknown search type')

    return request.formatter({
        'albumList': {
            'album': [
                f.as_subsonic_child(request.user)
                for f in query[offset:offset + size]
            ]
        }
    })
Exemple #15
0
def album_list_id3():
    ltype, size, offset = map(request.args.get, ['type', 'size', 'offset'])
    try:
        size = int(size) if size else 10
        offset = int(offset) if offset else 0
    except:
        return request.error_formatter(0, 'Invalid parameter format')

    query = store.find(Album)
    if ltype == 'random':
        albums = []
        count = query.count()

        if not count:
            return request.formatter({'albumList2': {}})

        for _ in xrange(size):
            x = random.choice(xrange(count))
            albums.append(query[x])

        return request.formatter({
            'albumList2': {
                'album': [a.as_subsonic_album(request.user) for a in albums]
            }
        })
    elif ltype == 'newest':
        query = query.find(Track.album_id == Album.id).group_by(
            Album.id).order_by(Desc(Min(Track.created)))
    elif ltype == 'frequent':
        query = query.find(Track.album_id == Album.id).group_by(
            Album.id).order_by(Desc(Avg(Track.play_count)))
    elif ltype == 'recent':
        query = query.find(Track.album_id == Album.id).group_by(
            Album.id).order_by(Desc(Max(Track.last_play)))
    elif ltype == 'starred':
        query = query.find(StarredAlbum.starred_id == Album.id,
                           User.id == StarredAlbum.user_id,
                           User.name == request.username)
    elif ltype == 'alphabeticalByName':
        query = query.order_by(Album.name)
    elif ltype == 'alphabeticalByArtist':
        query = query.find(Artist.id == Album.artist_id).order_by(
            Artist.name, Album.name)
    else:
        return request.error_formatter(0, 'Unknown search type')

    return request.formatter({
        'albumList2': {
            'album': [
                f.as_subsonic_album(request.user)
                for f in query[offset:offset + size]
            ]
        }
    })
Exemple #16
0
def download(typed):
    eid = request.args.get('id')
    cid = clean_id(eid)
    if not is_track_id(eid):
        return request.error_formatter(10, 'Invalid id')

    tr = typed.gettrack(cid)

    if tr is None or tr.path is None:
        return request.error_formatter(70, 'Track not found'), 404
    else:
        return send_file(tr.path, conditional=True)
Exemple #17
0
def song(typed):
    eid = request.args.get('id')
    cid = clean_id(eid)
    if not is_track_id(eid):
        return request.error_formatter(10, 'Missing or invalid Song id')

    tr = typed.gettrackfull(cid)

    if not tr:
        return request.error_formatter(70, 'Song not found'), 404

    return request.formatter({'song': format_track(tr)})
Exemple #18
0
def lyrics():
    artist, title = map(request.args.get, ['artist', 'title'])
    if not artist:
        return request.error_formatter(10, 'Missing artist parameter')
    if not title:
        return request.error_formatter(10, 'Missing title parameter')

    query = session.query(Track).join(Album, Artist).filter(
        func.lower(Track.title) == title.lower()
        and func.lower(Artist.name) == artist.lower())
    for track in query:
        lyrics_path = os.path.splitext(track.path)[0] + '.txt'
        if os.path.exists(lyrics_path):
            app.logger.debug('Found lyrics file: ' + lyrics_path)

            try:
                lyrics = read_file_as_unicode(lyrics_path)
            except UnicodeError:
                # Lyrics file couldn't be decoded. Rather than displaying an error, try with the potential next files or
                # return no lyrics. Log it anyway.
                app.logger.warn('Unsupported encoding for lyrics file ' +
                                lyrics_path)
                continue

            return request.formatter({
                'lyrics': {
                    'artist': track.album.artist.name,
                    'title': track.title,
                    '_value_': lyrics
                }
            })

    try:
        r = requests.get(
            "http://api.chartlyrics.com/apiv1.asmx/SearchLyricDirect",
            params={
                'artist': artist,
                'song': title
            })
        root = ElementTree.fromstring(r.content)

        ns = {'cl': 'http://api.chartlyrics.com/'}
        return request.formatter({
            'lyrics': {
                'artist': root.find('cl:LyricArtist', namespaces=ns).text,
                'title': root.find('cl:LyricSong', namespaces=ns).text,
                '_value_': root.find('cl:Lyric', namespaces=ns).text
            }
        })
    except requests.exceptions.RequestException, e:
        app.logger.warn('Error while requesting the ChartLyrics API: ' +
                        str(e))
Exemple #19
0
def album_list_id3():
    ltype, size, offset = map(request.args.get, ['type', 'size', 'offset'])
    try:
        size = int(size) if size else 10
        offset = int(offset) if offset else 0
    except:
        return request.error_formatter(0, 'Invalid parameter format')

    query = session.query(Album)
    if ltype == 'random':
        albums = []
        count = query.count()

        if not count:
            return request.formatter({'albumList2': {}})

        for _ in xrange(size):
            x = random.choice(xrange(count))
            albums.append(query.offset(x).limit(1).one())

        return request.formatter({
            'albumList2': {
                'album': [a.as_subsonic_album(request.user) for a in albums]
            }
        })
    elif ltype == 'newest':
        query = query.join(Track, Album.tracks).group_by(Album.id).order_by(
            desc(func.min(Track.created)))
    elif ltype == 'frequent':
        query = query.join(Track, Album.tracks).group_by(Album.id).order_by(
            desc(func.avg(Track.play_count)))
    elif ltype == 'recent':
        query = query.join(Track, Album.tracks).group_by(Album.id).order_by(
            desc(func.max(Track.last_play)))
    elif ltype == 'starred':
        query = query.join(StarredAlbum).join(User).filter(
            User.name == request.username)
    elif ltype == 'alphabeticalByName':
        query = query.order_by(Album.name)
    elif ltype == 'alphabeticalByArtist':
        query = query.join(Artist).order_by(Artist.name).order_by(Album.name)
    else:
        return request.error_formatter(0, 'Unknown search type')

    return request.formatter({
        'albumList2': {
            'album': [
                f.as_subsonic_album(request.user)
                for f in query.limit(size).offset(offset)
            ]
        }
    })
Exemple #20
0
def user_changepass():
    username, password = map(request.args.get, ['username', 'password'])
    if not username or not password:
        return request.error_formatter(10, 'Missing parameter')

    if username != request.username and not request.user.admin:
        return request.error_formatter(50, 'Admin restricted')

    status = UserManager.change_password2(store, username, password)
    if status != UserManager.SUCCESS:
        return request.error_formatter(0, UserManager.error_str(status))

    return request.formatter({})
Exemple #21
0
def user_info():
	username = request.values.get('username')
	if username is None:
		return request.error_formatter(10, 'Missing username')

	if username != request.username and not request.user.admin:
		return request.error_formatter(50, 'Admin restricted')

	user = store.find(User, User.name == username).one()
	if user is None:
		return request.error_formatter(0, 'Unknown user')

	return request.formatter({ 'user': user.as_subsonic_user() })
Exemple #22
0
def user_info():
    username = request.args.get('username')
    if username is None:
        return request.error_formatter(10, 'Missing username')

    if username != request.username and not request.user.admin:
        return request.error_formatter(50, 'Admin restricted')

    user = store.find(User, User.name == username).one()
    if user is None:
        return request.error_formatter(0, 'Unknown user')

    return request.formatter({'user': user.as_subsonic_user()})
Exemple #23
0
def user_info():
	username = request.args.get('username')
	if username is None:
		return request.error_formatter(10, 'Missing username')

	if username != request.username and not request.user.admin:
		return request.error_formatter(50, 'Admin restricted')

	user = User.query.filter(User.name == username).first()
	if user is None:
		return request.error_formatter(0, 'Unknown user')

	return request.formatter({ 'user': user.as_subsonic_user() })
Exemple #24
0
def user_changepass():
	username, password = map(request.args.get, [ 'username', 'password' ])
	if not username or not password:
		return request.error_formatter(10, 'Missing parameter')

	if username != request.username and not request.user.admin:
		return request.error_formatter(50, 'Admin restricted')

	status = UserManager.change_password2(username, password)
	if status != UserManager.SUCCESS:
		return request.error_formatter(0, UserManager.error_str(status))

	return request.formatter({})
Exemple #25
0
def _album_list(typed):
    ok, atype = check_parameter(request,
                                'type',
                                allow_none=False,
                                choices=[
                                    'random', 'newest', 'highest', 'frequent',
                                    'recent', 'starred', 'alphabeticalByName',
                                    'alphabeticalByArtist', 'byYear', 'genre'
                                ])
    if not ok:
        return False, atype
    ok, size = check_parameter(request,
                               'size',
                               fct=lambda val: int(val) if val else 10)
    if not ok:
        return False, size
    ok, offset = check_parameter(request,
                                 'offset',
                                 fct=lambda val: int(val) if val else 0)
    if not ok:
        return False, offset
    fromYear = request.args.get('fromYear')
    toYear = request.args.get('toYear')
    genre = request.args.get('genre')

    if atype == "byYear" and (not fromYear or not toYear):
        return False, request.error_formatter(
            10, 'Missing parameter fromYear or toYear')
    elif atype == "genre" and not genre:
        return False, request.error_formatter(10, 'Missing parameter genre')

    if atype == "random":
        count = typed.countalbums()

        def gen():
            for _ in range(size):
                x = random.choice(range(count))
                yield typed.getalbum(
                    ffilter=lambda query: query.offset(x).limit(1))

        return True, gen()
    else:
        fltr = get_filter_by_type(atype,
                                  fromYear=fromYear,
                                  toYear=toYear,
                                  genre=genre)
        srt = get_sort_by_type(atype)
        return True, typed.listalbums(fltr,
                                      skip=offset,
                                      limit=size,
                                      order_by=srt)
Exemple #26
0
def user_del():
	if not request.user.admin:
		return request.error_formatter(50, 'Admin restricted')

	username = request.values.get('username')
	user = store.find(User, User.name == username).one()
	if not user:
		return request.error_formatter(70, 'Unknown user')

	status = UserManager.delete(store, user.id)
	if status != UserManager.SUCCESS:
		return request.error_formatter(0, UserManager.error_str(status))

	return request.formatter({})
Exemple #27
0
def user_del():
	if not request.user.admin:
		return request.error_formatter(50, 'Admin restricted')

	username = request.args.get('username')
	user = User.query.filter(User.name == username).first()
	if not user:
		return request.error_formatter(70, 'Unknown user')

	status = UserManager.delete(user.id)
	if status != UserManager.SUCCESS:
		return request.error_formatter(0, UserManager.error_str(status))

	return request.formatter({})
Exemple #28
0
def album_list():
    ltype, size, offset = map(request.values.get, [ 'type', 'size', 'offset' ])
    if not ltype:
        return request.error_formatter(10, 'Missing type')
    try:
        size = int(size) if size else 10
        offset = int(offset) if offset else 0
    except:
        return request.error_formatter(0, 'Invalid parameter format')

    query = store.find(Folder, Track.folder_id == Folder.id)
    if ltype == 'random':
        albums = []
        count = query.count()

        if not count:
            return request.formatter({ 'albumList': {} })

        for _ in xrange(size):
            x = random.choice(xrange(count))
            albums.append(query[x])

        return request.formatter({
            'albumList': {
                'album': [ a.as_subsonic_child(request.user) for a in albums ]
            }
        })
    elif ltype == 'newest':
        query = query.order_by(Desc(Folder.created)).config(distinct = True)
    elif ltype == 'highest':
        query = query.find(RatingFolder.rated_id == Folder.id).group_by(Folder.id).order_by(Desc(Avg(RatingFolder.rating)))
    elif ltype == 'frequent':
        query = query.group_by(Folder.id).order_by(Desc(Avg(Track.play_count)))
    elif ltype == 'recent':
        query = query.group_by(Folder.id).order_by(Desc(Max(Track.last_play)))
    elif ltype == 'starred':
        query = query.find(StarredFolder.starred_id == Folder.id, User.id == StarredFolder.user_id, User.name == request.username)
    elif ltype == 'alphabeticalByName':
        query = query.order_by(Folder.name).config(distinct = True)
    elif ltype == 'alphabeticalByArtist':
        parent = ClassAlias(Folder)
        query = query.find(Folder.parent_id == parent.id).order_by(parent.name, Folder.name).config(distinct = True)
    else:
        return request.error_formatter(0, 'Unknown search type')

    return request.formatter({
        'albumList': {
            'album': [ f.as_subsonic_child(request.user) for f in query[offset:offset+size] ]
        }
    })
Exemple #29
0
def check_parameter(request, key, allow_none=True, choices=None, fct=None):
    val = request.args.get(key)
    if val is None and not allow_none:
        return False, request.error_formatter(10, 'Missing parameter %s' % key)
    if choices is not None and val not in choices:
        return False, request.error_formatter(
            0, 'Invalid value %s for parameter %s' % (val, key))
    if fct is not None:
        try:
            return True, fct(val)
        except:
            return False, request.error_formatter(0,
                                                  'Invalid parameter %s' % key)
    return True, val
Exemple #30
0
def album_list():
	ltype, size, offset = map(request.args.get, [ 'type', 'size', 'offset' ])
	try:
		size = int(size) if size else 10
		offset = int(offset) if offset else 0
	except:
		return request.error_formatter(0, 'Invalid parameter format')

	query = session.query(Folder).filter(Folder.tracks.any())
	if ltype == 'random':
		albums = []
		count = query.count()

		if not count:
			return request.formatter({ 'albumList': {} })

		for _ in xrange(size):
			x = random.choice(xrange(count))
			albums.append(query.offset(x).limit(1).one())

		return request.formatter({
			'albumList': {
				'album': [ a.as_subsonic_child(request.user) for a in albums ]
			}
		})
	elif ltype == 'newest':
		query = query.order_by(desc(Folder.created))
	elif ltype == 'highest':
		query = query.join(RatingFolder).group_by(Folder.id).order_by(desc(func.avg(RatingFolder.rating)))
	elif ltype == 'frequent':
		query = query.join(Track, Folder.tracks).group_by(Folder.id).order_by(desc(func.avg(Track.play_count)))
	elif ltype == 'recent':
		query = query.join(Track, Folder.tracks).group_by(Folder.id).order_by(desc(func.max(Track.last_play)))
	elif ltype == 'starred':
		query = query.join(StarredFolder).join(User).filter(User.name == request.username)
	elif ltype == 'alphabeticalByName':
		query = query.order_by(Folder.name)
	elif ltype == 'alphabeticalByArtist':
		# this is a mess because who knows how your file structure is set up
		# with the database changes it's more difficult to get the parent of a dir
		parent = aliased(Folder)
		query = query.join(parent, Folder.parent).order_by(parent.name).order_by(Folder.name)
	else:
		return request.error_formatter(0, 'Unknown search type')

	return request.formatter({
		'albumList': {
			'album': [ f.as_subsonic_child(request.user) for f in query.limit(size).offset(offset) ]
		}
	})
Exemple #31
0
def user_del():
    if not request.user.admin:
        return request.error_formatter(50, 'Admin restricted')

    username = request.args.get('username')
    user = store.find(User, User.name == username).one()
    if not user:
        return request.error_formatter(70, 'Unknown user')

    status = UserManager.delete(store, user.id)
    if status != UserManager.SUCCESS:
        return request.error_formatter(0, UserManager.error_str(status))

    return request.formatter({})
Exemple #32
0
def user_add():
	if not request.user.admin:
		return request.error_formatter(50, 'Admin restricted')

	username, password, email, admin = map(request.args.get, [ 'username', 'password', 'email', 'adminRole' ])
	if not username or not password or not email:
		return request.error_formatter(10, 'Missing parameter')
	admin = True if admin in (True, 'True', 'true', 1, '1') else False

	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')

	return request.formatter({})
Exemple #33
0
	def try_star(ent, starred_ent, eid):
		try:
			uid = uuid.UUID(eid)
		except:
			return 2, request.error_formatter(0, 'Invalid %s id' % ent.__name__)

		if starred_ent.query.get((request.user.id, uid)):
			return 2, request.error_formatter(0, '%s already starred' % ent.__name__)
		e = ent.query.get(uid)
		if e:
			session.add(starred_ent(user = request.user, starred = e))
		else:
			return 1, request.error_formatter(70, 'Unknown %s id' % ent.__name__)

		return 0, None
Exemple #34
0
def list_playlists():
    query = store.find(Playlist, Or(Playlist.user_id == request.user.id, Playlist.public == True)).order_by(Playlist.name)

    username = request.values.get('username')
    if username:
        if not request.user.admin:
            return request.error_formatter(50, 'Restricted to admins')

        user = store.find(User, User.name == username).one()
        if not user:
            return request.error_formatter(70, 'No such user')

        query = store.find(Playlist, Playlist.user_id == User.id, User.name == username).order_by(Playlist.name)

    return request.formatter({ 'playlists': { 'playlist': [ p.as_subsonic_playlist(request.user) for p in query ] } })
Exemple #35
0
def new_search():
    query, artist_count, artist_offset, album_count, album_offset, song_count, song_offset = map(
        request.values.get, [
            'query', 'artistCount', 'artistOffset', 'albumCount',
            'albumOffset', 'songCount', 'songOffset'
        ])

    try:
        artist_count = int(artist_count) if artist_count else 20
        artist_offset = int(artist_offset) if artist_offset else 0
        album_count = int(album_count) if album_count else 20
        album_offset = int(album_offset) if album_offset else 0
        song_count = int(song_count) if song_count else 20
        song_offset = int(song_offset) if song_offset else 0
    except:
        return request.error_formatter(0, 'Invalid parameter')

    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]

    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
            ]
        }
    })
Exemple #36
0
def authorize():
    if not request.path.startswith('/rest/'):
        return

    error = request.error_formatter(40, 'Unauthorized'), 401

    if request.authorization:
        status, user = UserManager.try_auth(store,
                                            request.authorization.username,
                                            request.authorization.password)
        if status == UserManager.SUCCESS:
            request.username = request.authorization.username
            request.user = user
            return

    (username, password) = map(request.values.get, ['u', 'p'])
    if not username or not password:
        return error

    password = decode_password(password)
    status, user = UserManager.try_auth(store, username, password)
    if status != UserManager.SUCCESS:
        return error

    request.username = username
    request.user = user
Exemple #37
0
def music_directory(typed):
    eid = request.args.get('id')
    cid = clean_id(eid)
    if is_artist_id(eid):
        dirlist = typed.listalbumsbyartists(
            lambda query: query.filter(Artist.id == cid))
        children = dirlist[0].albums
        format_directory_id = format_artist_id
        format_child = format_album
    elif is_album_id(eid):
        dirlist = typed.listtracksbyalbums(
            lambda query: query.filter(Album.id == cid))
        children = dirlist[0].tracks
        format_directory_id = format_album_id
        format_child = format_track
    else:
        return request.error_formatter(10, 'Missing or invalid id')

    return request.formatter({
        'directory': {
            'id': format_directory_id(dirlist[0].id),
            'name': dirlist[0].name,
            'child': [format_child(child, child=True) for child in children]
        }
    })
Exemple #38
0
def user_add():
    if not request.user.admin:
        return request.error_formatter(50, 'Admin restricted')

    username, password, email, admin = map(
        request.args.get, ['username', 'password', 'email', 'adminRole'])
    if not username or not password or not email:
        return request.error_formatter(10, 'Missing parameter')
    admin = True if admin in (True, 'True', 'true', 1, '1') else False

    status = UserManager.add(store, username, password, email, admin)
    if status == UserManager.NAME_EXISTS:
        return request.error_formatter(
            0, 'There is already a user with that username')

    return request.formatter({})
Exemple #39
0
def album_list_id3():
    ltype, size, offset = map(request.values.get, [ 'type', 'size', 'offset' ])
    if not ltype:
        return request.error_formatter(10, 'Missing type')
    try:
        size = int(size) if size else 10
        offset = int(offset) if offset else 0
    except:
        return request.error_formatter(0, 'Invalid parameter format')

    query = store.find(Album)
    if ltype == 'random':
        albums = []
        count = query.count()

        if not count:
            return request.formatter({ 'albumList2': {} })

        for _ in xrange(size):
            x = random.choice(xrange(count))
            albums.append(query[x])

        return request.formatter({
            'albumList2': {
                'album': [ a.as_subsonic_album(request.user) for a in albums ]
            }
        })
    elif ltype == 'newest':
        query = query.find(Track.album_id == Album.id).group_by(Album.id).order_by(Desc(Min(Track.created)))
    elif ltype == 'frequent':
        query = query.find(Track.album_id == Album.id).group_by(Album.id).order_by(Desc(Avg(Track.play_count)))
    elif ltype == 'recent':
        query = query.find(Track.album_id == Album.id).group_by(Album.id).order_by(Desc(Max(Track.last_play)))
    elif ltype == 'starred':
        query = query.find(StarredAlbum.starred_id == Album.id, User.id == StarredAlbum.user_id, User.name == request.username)
    elif ltype == 'alphabeticalByName':
        query = query.order_by(Album.name)
    elif ltype == 'alphabeticalByArtist':
        query = query.find(Artist.id == Album.artist_id).order_by(Artist.name, Album.name)
    else:
        return request.error_formatter(0, 'Unknown search type')

    return request.formatter({
        'albumList2': {
            'album': [ f.as_subsonic_album(request.user) for f in query[offset:offset+size] ]
        }
    })
Exemple #40
0
def add_chat_message():
    msg = request.args.get("message")
    if not msg:
        return request.error_formatter(10, "Missing message")

    session.add(ChatMessage(user=request.user, message=msg))
    session.commit()
    return request.formatter({})
Exemple #41
0
def user_changepass():
    username, password = map(request.values.get, [ 'username', 'password' ])
    if not username or not password:
        return request.error_formatter(10, 'Missing parameter')

    if username != request.username and not request.user.admin:
        return request.error_formatter(50, 'Admin restricted')

    password = decode_password(password)
    status = UserManager.change_password2(store, username, password)
    if status != UserManager.SUCCESS:
        code = 0
        if status == UserManager.NO_SUCH_USER:
            code = 70
        return request.error_formatter(code, UserManager.error_str(status))

    return request.formatter({})
Exemple #42
0
	def try_unstar(ent, eid):
		try:
			uid = uuid.UUID(eid)
		except:
			return request.error_formatter(0, 'Invalid id')

		ent.query.filter(ent.user_id == request.user.id).filter(ent.starred_id == uid).delete()
		return None
Exemple #43
0
def add_chat_message():
	msg = request.args.get('message')
	if not msg:
		return request.error_formatter(10, 'Missing message')

	session.add(ChatMessage(user = request.user, message = msg))
	session.commit()
	return request.formatter({})
Exemple #44
0
def user_changepass():
    username, password = map(request.values.get, ['username', 'password'])
    if not username or not password:
        return request.error_formatter(10, 'Missing parameter')

    if username != request.username and not request.user.admin:
        return request.error_formatter(50, 'Admin restricted')

    password = decode_password(password)
    status = UserManager.change_password2(store, username, password)
    if status != UserManager.SUCCESS:
        code = 0
        if status == UserManager.NO_SUCH_USER:
            code = 70
        return request.error_formatter(code, UserManager.error_str(status))

    return request.formatter({})
Exemple #45
0
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)]
        }})
Exemple #46
0
	def try_unstar(ent, eid):
		try:
			uid = uuid.UUID(eid)
		except:
			return request.error_formatter(0, 'Invalid id')

		store.find(ent, ent.user_id == request.user.id, ent.starred_id == uid).remove()
		return None
Exemple #47
0
def album_list_id3():
	ltype, size, offset = map(request.args.get, [ 'type', 'size', 'offset' ])
	try:
		size = int(size) if size else 10
		offset = int(offset) if offset else 0
	except:
		return request.error_formatter(0, 'Invalid parameter format')

	query = session.query(Album)
	if ltype == 'random':
		albums = []
		count = query.count()

		if not count:
			return request.formatter({ 'albumList2': {} })

		for _ in xrange(size):
			x = random.choice(xrange(count))
			albums.append(query.offset(x).limit(1).one())

		return request.formatter({
			'albumList2': {
				'album': [ a.as_subsonic_album(request.user) for a in albums ]
			}
		})
	elif ltype == 'newest':
		query = query.join(Track, Album.tracks).group_by(Album.id).order_by(desc(func.min(Track.created)))
	elif ltype == 'frequent':
		query = query.join(Track, Album.tracks).group_by(Album.id).order_by(desc(func.avg(Track.play_count)))
	elif ltype == 'recent':
		query = query.join(Track, Album.tracks).group_by(Album.id).order_by(desc(func.max(Track.last_play)))
	elif ltype == 'starred':
		query = query.join(StarredAlbum).join(User).filter(User.name == request.username)
	elif ltype == 'alphabeticalByName':
		query = query.order_by(Album.name)
	elif ltype == 'alphabeticalByArtist':
		query = query.join(Artist).order_by(Artist.name).order_by(Album.name)
	else:
		return request.error_formatter(0, 'Unknown search type')

	return request.formatter({
		'albumList2': {
			'album': [ f.as_subsonic_album(request.user) for f in query.limit(size).offset(offset) ]
		}
	})
Exemple #48
0
    def try_unstar(ent, eid):
        try:
            uid = uuid.UUID(eid)
        except:
            return request.error_formatter(0, 'Invalid id')

        store.find(ent, ent.user_id == request.user.id,
                   ent.starred_id == uid).remove()
        return None
Exemple #49
0
    def try_unstar(ent, eid):
        try:
            uid = uuid.UUID(eid)
        except:
            return request.error_formatter(0, 'Invalid id')

        session.query(ent).filter(ent.user_id == request.user.id).filter(
            ent.starred_id == uid).delete()
        return None
Exemple #50
0
	def try_star(ent, starred_ent, eid):
		try:
			uid = uuid.UUID(eid)
		except:
			return 2, request.error_formatter(0, 'Invalid %s id' % ent.__name__)

		if store.get(starred_ent, (request.user.id, uid)):
			return 2, request.error_formatter(0, '%s already starred' % ent.__name__)
		e = store.get(ent, uid)
		if e:
			starred = starred_ent()
			starred.user_id = request.user.id
			starred.starred_id = uid
			store.add(starred)
		else:
			return 1, request.error_formatter(70, 'Unknown %s id' % ent.__name__)

		return 0, None
Exemple #51
0
def update_playlist():
    status, res = get_entity(request, Playlist, 'playlistId')
    if not status:
        return res

    if res.user_id != request.user.id and not request.user.admin:
        return request.error_formatter(
            50, "You're not allowed to delete a playlist that isn't yours")

    playlist = res
    name, comment, public = map(request.args.get,
                                ['name', 'comment', 'public'])
    to_add, to_remove = map(request.args.getlist,
                            ['songIdToAdd', 'songIndexToRemove'])
    try:
        to_add = set(map(uuid.UUID, to_add))
        to_remove = sorted(set(map(int, to_remove)))
    except:
        return request.error_formatter(0, 'Invalid parameter')

    if name:
        playlist.name = name
    if comment:
        playlist.comment = comment
    if public:
        playlist.public = public in (True, 'True', 'true', 1, '1')

    for sid in to_add:
        track = Track.query.get(sid)
        if not track:
            return request.error_formatter(70, 'Unknown song')
        if track not in playlist.tracks:
            playlist.tracks.append(track)

    offset = 0
    for idx in to_remove:
        idx = idx - offset
        if idx < 0 or idx >= len(playlist.tracks):
            return request.error_formatter(0, 'Index out of range')
        playlist.tracks.pop(idx)
        offset += 1

    session.commit()
    return request.formatter({})
Exemple #52
0
def album(typed):
    eid = request.args.get('id')
    cid = clean_id(eid)
    if not is_album_id(eid):
        return request.error_formatter(10, 'Missing or invalid Album id')

    al = typed.listtracksbyalbums(lambda query: query.filter(Album.id == cid))

    if len(al) == 0:
        return request.error_formatter(70, 'Album not found'), 404

    return request.formatter({
        'album': {
            'id': format_album_id(cid),
            'name': al[0].name,
            'albumCount': al[0].track_count(),
            'song': [format_track(track) for track in al[0].tracks]
        }
    })
Exemple #53
0
def cover_art(typed):
    eid = request.args.get('id')
    cid = clean_id(eid)
    if not is_track_id(eid) and not is_album_id(eid):
        return request.error_formatter(10, 'Invalid id')

    if is_track_id(eid):
        tr = typed.gettrackinfo(cid)
        if tr is None or tr.album_id is None:
            return request.error_formatter(70, 'Cover art not found'), 404
        else:
            cid = tr.album_id
    cover = typed.getcoverbyalbumid(cid)
    if cover is None or cover.mbid == '0':
        return request.error_formatter(70, 'Cover art not found'), 404
    else:
        return send_from_directory(Thumb.getdir(),
                                   os.path.basename(cover.path),
                                   conditional=True)
Exemple #54
0
def search2and3(typed):
    q = request.args.get('query')
    if not q:
        return request.error_formatter(10, 'Missing query parameter')
    ok, artistCount = check_parameter(request,
                                      'artistCount',
                                      fct=lambda val: int(val) if val else 20)
    if not ok:
        return False, artistCount
    ok, artistOffset = check_parameter(request,
                                       'artistOffset',
                                       fct=lambda val: int(val) if val else 0)
    if not ok:
        return False, artistOffset
    ok, albumCount = check_parameter(request,
                                     'albumCount',
                                     fct=lambda val: int(val) if val else 20)
    if not ok:
        return False, albumCount
    ok, albumOffset = check_parameter(request,
                                      'albumOffset',
                                      fct=lambda val: int(val) if val else 0)
    if not ok:
        return False, albumOffset
    ok, songCount = check_parameter(request,
                                    'songCount',
                                    fct=lambda val: int(val) if val else 20)
    if not ok:
        return False, songCount
    ok, songOffset = check_parameter(request,
                                     'songOffset',
                                     fct=lambda val: int(val) if val else 0)
    if not ok:
        return False, songOffset

    artists = typed.listartists(
        lambda query: query.filter(Artist.name.contains(q)),
        skip=artistOffset,
        limit=artistCount)
    albums = typed.listalbums(
        lambda query: query.filter(Album.name.contains(q)),
        skip=albumOffset,
        limit=albumCount)
    tracks = typed.listtracks(
        lambda query: query.filter(TrackInfo.name.contains(q)),
        skip=songOffset,
        limit=songCount)

    return request.formatter({
        'searchResult2': {
            'artist': [format_artist(artist) for artist in artists],
            'album': [format_album(album) for album in albums],
            'track': [format_track(track) for track in tracks]
        }
    })
Exemple #55
0
def create_playlist():
    # Only(?) method where the android client uses form data rather than GET params
    playlist_id, name = map(
        lambda x: request.args.get(x) or request.form.get(x),
        ['playlistId', 'name'])
    # songId actually doesn't seem to be required
    songs = request.args.getlist('songId') or request.form.getlist('songId')
    try:
        playlist_id = uuid.UUID(playlist_id) if playlist_id else None
        songs = set(map(uuid.UUID, songs))
    except:
        return request.error_formatter(0, 'Invalid parameter')

    if playlist_id:
        playlist = store.get(Playlist, playlist_id)
        if not playlist:
            return request.error_formatter(70, 'Unknwon playlist')

        if playlist.user_id != request.user.id and not request.user.admin:
            return request.error_formatter(
                50, "You're not allowed to modify a playlist that isn't yours")

        playlist.tracks.clear()
        if name:
            playlist.name = name
    elif name:
        playlist = Playlist()
        playlist.user_id = request.user.id
        playlist.name = name
        store.add(playlist)
    else:
        return request.error_formatter(10, 'Missing playlist id or name')

    for sid in songs:
        track = store.get(Track, sid)
        if not track:
            return request.error_formatter(70, 'Unknown song')

        playlist.tracks.add(track)

    store.commit()
    return request.formatter({})
Exemple #56
0
def search_id3():
    query, artist_count, artist_offset, album_count, album_offset, song_count, song_offset = map(
        request.values.get, [
            'query', 'artistCount', 'artistOffset', 'albumCount',
            'albumOffset', 'songCount', 'songOffset'
        ])

    try:
        artist_count = int(artist_count) if artist_count else 20
        artist_offset = int(artist_offset) if artist_offset else 0
        album_count = int(album_count) if album_count else 20
        album_offset = int(album_offset) if album_offset else 0
        song_count = int(song_count) if song_count else 20
        song_offset = int(song_offset) if song_offset else 0
    except:
        return request.error_formatter(0, 'Invalid parameter')

    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]

    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
            ]
        }
    })
Exemple #57
0
def add_chat_message():
	msg = request.args.get('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()
	return request.formatter({})
Exemple #58
0
def list_playlists():
	query = Playlist.query.filter(or_(Playlist.user_id == request.user.id, Playlist.public == True)).order_by(func.lower(Playlist.name))

	username = request.args.get('username')
	if username:
		if not request.user.admin:
			return request.error_formatter(50, 'Restricted to admins')

		query = Playlist.query.join(User).filter(User.name == username).order_by(func.lower(Playlist.name))

	return request.formatter({ 'playlists': { 'playlist': [ p.as_subsonic_playlist(request.user) for p in query ] } })
Exemple #59
0
def delete_playlist():
    status, res = get_entity(request, Playlist)
    if not status:
        return res

    if res.user_id != request.user.id and not request.user.admin:
        return request.error_formatter(50, "You're not allowed to delete a playlist that isn't yours")

    store.remove(res)
    store.commit()
    return request.formatter({})
Exemple #60
0
def show_playlist():
    status, res = get_entity(request, Playlist)
    if not status:
        return res

    if res.user_id != request.user.id and not request.user.admin:
        return request.error_formatter('50', 'Private playlist')

    info = res.as_subsonic_playlist(request.user)
    info['entry'] = [ t.as_subsonic_child(request.user, request.prefs) for t in res.get_tracks() ]
    return request.formatter({ 'playlist': info })