Example #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 ]
	}})
Example #2
0
def index():
    stats = {
        'artists': store.find(Artist).count(),
        'albums': store.find(Album).count(),
        'tracks': store.find(Track).count()
    }
    return render_template('home.html', stats = stats, admin = UserManager.get(store, session.get('userid'))[1].admin)
Example #3
0
def do_user_import():
	if not request.files['file']:
		return render_template('importusers.html', admin = UserManager.get(store, session.get('userid'))[1].admin)

	users = []
	reader = csv.reader(request.files['file'])
	for id, name, mail, password, salt, admin, lfmsess, lfmstatus in reader:
		mail = None if mail == 'None' else mail
		admin = admin == 'True'
		lfmsess = None if lfmsess == 'None' else lfmsess
		lfmstatus = lfmstatus == 'True'

		user = User()
		user.id = uuid.UUID(id)
		user.name = name
		user.password = password
		user.salt = salt
		user.admin = admin
		user.lastfm_session = lfmsess
		user.lastfm_status = lfmstatus

		users.append(user)

	store.find(User).remove()
	for u in users:
		store.add(u)
	store.commit()

	return redirect(url_for('user_index'))
Example #4
0
def do_user_import():
	if not request.files['file']:
		return render_template('importusers.html')

	users = []
	reader = csv.reader(request.files['file'])
	for id, name, mail, password, salt, admin, lfmsess, lfmstatus in reader:
		mail = None if mail == 'None' else mail
		admin = admin == 'True'
		lfmsess = None if lfmsess == 'None' else lfmsess
		lfmstatus = lfmstatus == 'True'

		user = User()
		user.id = uuid.UUID(id)
		user.name = name
		user.password = password
		user.salt = salt
		user.admin = admin
		user.lastfm_session = lfmsess
		user.lastfm_status = lfmstatus

		users.append(user)

	store.find(User).remove()
	for u in users:
		store.add(u)
	store.commit()

	return redirect(url_for('user_index'))
Example #5
0
def get_starred():
    folders = store.find(StarredFolder, StarredFolder.user_id == User.id,
                         User.name == request.username)

    return request.formatter({
        'starred': {
            'artist': [{
                'id': str(sf.starred_id),
                'name': sf.starred.name
            } for sf in folders.find(
                Folder.parent_id == StarredFolder.starred_id, Track.folder_id
                == Folder.id).config(distinct=True)],
            'album': [
                sf.starred.as_subsonic_child(request.user)
                for sf in folders.find(
                    Track.folder_id == StarredFolder.starred_id).config(
                        distinct=True)
            ],
            'song': [
                st.starred.as_subsonic_child(request.user)
                for st in store.find(StarredTrack, StarredTrack.user_id ==
                                     User.id, User.name == request.username)
            ]
        }
    })
Example #6
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 = 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({ '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 ]
	}})
Example #7
0
def get_starred_id3():
	return request.formatter({
		'starred2': {
			'artist': [ sa.starred.as_subsonic_artist(request.user) for sa in store.find(StarredArtist, StarredArtist.user_id == User.id, User.name == request.username) ],
			'album': [ sa.starred.as_subsonic_album(request.user) for sa in store.find(StarredAlbum, StarredAlbum.user_id == User.id, User.name == request.username) ],
			'song': [ st.starred.as_subsonic_child(request.user) for st in store.find(StarredTrack, StarredTrack.user_id == User.id, User.name == request.username) ]
		}
	})
Example #8
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
Example #9
0
def get_starred_id3():
    return request.formatter({
        'starred2': {
            'artist': [ sa.starred.as_subsonic_artist(request.user) for sa in store.find(StarredArtist, StarredArtist.user_id == User.id, User.name == request.username) ],
            'album': [ sa.starred.as_subsonic_album(request.user) for sa in store.find(StarredAlbum, StarredAlbum.user_id == User.id, User.name == request.username) ],
            'song': [ st.starred.as_subsonic_child(request.user, request.prefs) for st in store.find(StarredTrack, StarredTrack.user_id == User.id, User.name == request.username) ]
        }
    })
Example #10
0
def user_profile(uid):
	if uid == 'me':
		prefs = store.find(ClientPrefs, ClientPrefs.user_id == uuid.UUID(session.get('userid')))
		return render_template('profile.html', user = UserManager.get(store, session.get('userid'))[1], api_key = config.get('lastfm', 'api_key'), clients = prefs, admin = UserManager.get(store, session.get('userid'))[1].admin)
	else:
		if not UserManager.get(store, session.get('userid'))[1].admin or not UserManager.get(store, uid)[0] is UserManager.SUCCESS:
			return redirect(url_for('index'))
		prefs = store.find(ClientPrefs, ClientPrefs.user_id == uuid.UUID(uid))
		return render_template('profile.html', user = UserManager.get(store, uid)[1], api_key = config.get('lastfm', 'api_key'), clients = prefs, admin = UserManager.get(store, session.get('userid'))[1].admin)
Example #11
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
Example #12
0
def get_starred():
	folders = store.find(StarredFolder, StarredFolder.user_id == User.id, User.name == request.username)

	return request.formatter({
		'starred': {
			'artist': [ { 'id': str(sf.starred_id), 'name': sf.starred.name } for sf in folders.find(Folder.parent_id == StarredFolder.starred_id, Track.folder_id == Folder.id).config(distinct = True) ],
			'album': [ sf.starred.as_subsonic_child(request.user) for sf in folders.find(Track.folder_id == StarredFolder.starred_id).config(distinct = True) ],
			'song': [ st.starred.as_subsonic_child(request.user) for st in store.find(StarredTrack, StarredTrack.user_id == User.id, User.name == request.username) ]
		}
	})
Example #13
0
def index():
    stats = {
        'artists': store.find(Artist).count(),
        'albums': store.find(Album).count(),
        'tracks': store.find(Track).count()
    }
    return render_template('home.html',
                           stats=stats,
                           admin=UserManager.get(
                               store, session.get('userid'))[1].admin)
Example #14
0
def list_playlists():
	query = store.find(Playlist, Or(Playlist.user_id == request.user.id, Playlist.public == True)).order_by(Playlist.name)

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

		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 ] } })
Example #15
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")

        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]}})
Example #16
0
def try_unstar(starred_ent, eid):
    """ Unstars an entity

    :param starred_ent: class used for the db representation of the starring of the entity
    :param eid: id of the entity to unstar
    :return error dict, if any. None otherwise
    """

    try:
        uid = uuid.UUID(eid)
    except:
        return { 'code': 0, 'message': 'Invalid id {}'.format(eid) }

    store.find(starred_ent, starred_ent.user_id == request.user.id, starred_ent.starred_id == uid).remove()
    return None
Example #17
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
            ]
        }
    })
Example #18
0
def change_username_post(uid):
    code, user = UserManager.get(store, uid)
    if code != UserManager.SUCCESS:
        return redirect(url_for('index'))

    username = request.form.get('user')
    if username in ('', None):
        flash('The username is required')
        return render_template('change_username.html', user = user)
    if user.name != username and store.find(User, User.name == username).one():
        flash('This name is already taken')
        return render_template('change_username.html', user = user)

    if request.form.get('admin') is None:
        admin = False
    else:
        admin = True

    if user.name != username or user.admin != admin:
        user.name = username
        user.admin = admin
        store.commit()
        flash("User '%s' updated." % username)
    else:
        flash("No changes for '%s'." % username)

    return redirect(url_for('user_profile', uid = uid))
Example #19
0
def list_artists():
    # According to the API page, there are no parameters?
    indexes = {}
    for artist in store.find(Artist):
        index = artist.name[0].upper() if artist.name else '?'
        if index in map(str, xrange(10)):
            index = '#'
        elif index not in string.letters:
            index = '?'

        if index not in indexes:
            indexes[index] = []

        indexes[index].append(artist)

    return request.formatter({
        'artists': {
            'index': [{
                'name':
                k,
                'artist': [
                    a.as_subsonic_artist(request.user)
                    for a in sorted(v, key=lambda a: a.name.lower())
                ]
            } for k, v in sorted(indexes.iteritems())]
        }
    })
Example #20
0
def add_user():
	if request.method == 'GET':
		return render_template('adduser.html', admin = UserManager.get(store, session.get('userid'))[1].admin)

	error = False
	(name, passwd, passwd_confirm, mail, admin) = map(request.form.get, [ 'user', 'passwd', 'passwd_confirm', 'mail', 'admin' ])
	if name in (None, ''):
		flash('The name is required.')
		error = True
	if passwd in (None, ''):
		flash('Please provide a password.')
		error = True
	elif passwd != passwd_confirm:
		flash("The passwords don't match.")
		error = True

	if admin is None:
		admin = True if store.find(User, User.admin == True).count() == 0 else False
	else:
		admin = True

	if not error:
		status = UserManager.add(store, name, passwd, mail, admin)
		if status == UserManager.SUCCESS:
			flash("User '%s' successfully added" % name)
			return redirect(url_for('user_index'))
		else:
			flash(UserManager.error_str(status))

	return render_template('adduser.html', admin = UserManager.get(store, session.get('userid'))[1].admin)
Example #21
0
def add_user_post():
    error = False
    (name, passwd, passwd_confirm, mail, admin) = map(request.form.get, [ 'user', 'passwd', 'passwd_confirm', 'mail', 'admin' ])
    if not name:
        flash('The name is required.')
        error = True
    if not passwd:
        flash('Please provide a password.')
        error = True
    elif passwd != passwd_confirm:
        flash("The passwords don't match.")
        error = True

    if admin is None:
        admin = True if store.find(User, User.admin == True).count() == 0 else False
    else:
        admin = True

    if not error:
        status = UserManager.add(store, name, passwd, mail, admin)
        if status == UserManager.SUCCESS:
            flash("User '%s' successfully added" % name)
            return redirect(url_for('user_index'))
        else:
            flash(UserManager.error_str(status))

    return add_user_form()
Example #22
0
def try_unstar(starred_ent, eid):
    """ Unstars an entity

    :param starred_ent: class used for the db representation of the starring of the entity
    :param eid: id of the entity to unstar
    :return error dict, if any. None otherwise
    """

    try:
        uid = uuid.UUID(eid)
    except:
        return {'code': 0, 'message': 'Invalid id {}'.format(eid)}

    store.find(starred_ent, starred_ent.user_id == request.user.id,
               starred_ent.starred_id == uid).remove()
    return None
Example #23
0
def add_user_post():
    error = False
    (name, passwd, passwd_confirm, mail, admin) = map(request.form.get, [ 'user', 'passwd', 'passwd_confirm', 'mail', 'admin' ])
    if not name:
        flash('The name is required.')
        error = True
    if not passwd:
        flash('Please provide a password.')
        error = True
    elif passwd != passwd_confirm:
        flash("The passwords don't match.")
        error = True

    if admin is None:
        admin = True if store.find(User, User.admin == True).count() == 0 else False
    else:
        admin = True

    if not error:
        status = UserManager.add(store, name, passwd, mail, admin)
        if status == UserManager.SUCCESS:
            flash("User '%s' successfully added" % name)
            return redirect(url_for('user_index'))
        else:
            flash(UserManager.error_str(status))

    return add_user_form()
Example #24
0
def change_username_post(uid):
    code, user = UserManager.get(store, uid)
    if code != UserManager.SUCCESS:
        return redirect(url_for('index'))

    username = request.form.get('user')
    if username in ('', None):
        flash('The username is required')
        return render_template('change_username.html', user = user)
    if user.name != username and store.find(User, User.name == username).one():
        flash('This name is already taken')
        return render_template('change_username.html', user = user)

    if request.form.get('admin') is None:
        admin = False
    else:
        admin = True

    if user.name != username or user.admin != admin:
        user.name = username
        user.admin = admin
        store.commit()
        flash("User '%s' updated." % username)
    else:
        flash("No changes for '%s'." % username)

    return redirect(url_for('user_profile', uid = uid))
Example #25
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)]
        }})
Example #26
0
def list_folders():
	return request.formatter({
		'musicFolders': {
			'musicFolder': [ {
				'id': str(f.id),
				'name': f.name
			} for f in store.find(Folder, Folder.root == True).order_by(Folder.name) ]
		}
	})
Example #27
0
def list_playlists():
    query = store.find(
        Playlist,
        Or(Playlist.user_id == request.user.id,
           Playlist.public == True)).order_by(Playlist.name)

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

        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]
        }
    })
Example #28
0
def list_folders():
    return request.formatter({
        'musicFolders': {
            'musicFolder': [{
                'id': str(f.id),
                'name': f.name
            } for f in store.find(Folder, Folder.root == True).order_by(
                Folder.name)]
        }
    })
Example #29
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]
            ]
        }
    })
Example #30
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
            ]
        }
    })
Example #31
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]
            ]
        }
    })
Example #32
0
def now_playing():
	query = store.find(User, Track.id == User.last_play_id)

	return request.formatter({
		'nowPlaying': {
			'entry': [ dict(
				u.last_play.as_subsonic_child(request.user).items() +
				{ 'username': u.name, 'minutesAgo': (now() - u.last_play_date).seconds / 60, 'playerId': 0 }.items()
			) for u in query if u.last_play_date + timedelta(seconds = u.last_play.duration * 2) > now() ]
		}
	})
Example #33
0
def now_playing():
    query = store.find(User, Track.id == User.last_play_id)

    return request.formatter({
        'nowPlaying': {
            'entry': [ dict(
                u.last_play.as_subsonic_child(request.user, request.prefs).items() +
                { 'username': u.name, 'minutesAgo': (now() - u.last_play_date).seconds / 60, 'playerId': 0 }.items()
            ) for u in query if u.last_play_date + timedelta(seconds = u.last_play.duration * 2) > now() ]
        }
    })
Example #34
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:
        store.find(RatingTrack, RatingTrack.user_id == request.user.id,
                   RatingTrack.rated_id == uid).remove()
        store.find(RatingFolder, RatingFolder.user_id == request.user.id,
                   RatingFolder.rated_id == uid).remove()
    else:
        rated = store.get(Track, uid)
        rating_ent = RatingTrack
        if not rated:
            rated = store.get(Folder, uid)
            rating_ent = RatingFolder
            if not rated:
                return request.error_formatter(70, 'Unknown id')

        rating_info = store.get(rating_ent, (request.user.id, uid))
        if rating_info:
            rating_info.rating = rating
        else:
            rating_info = rating_ent()
            rating_info.user_id = request.user.id
            rating_info.rated_id = uid
            rating_info.rating = rating
            store.add(rating_info)

    store.commit()
    return request.formatter({})
Example #35
0
def get_chat():
	since = request.args.get('since')
	try:
		since = int(since) / 1000 if since else None
	except:
		return request.error_formatter(0, 'Invalid parameter')

	query = store.find(ChatMessage).order_by(ChatMessage.time)
	if since:
		query = query.find(ChatMessage.time > since)

	return request.formatter({ 'chatMessages': { 'chatMessage': [ msg.responsize() for msg in query ] }})
Example #36
0
def get_chat():
    since = request.values.get('since')
    try:
        since = int(since) / 1000 if since else None
    except:
        return request.error_formatter(0, 'Invalid parameter')

    query = store.find(ChatMessage).order_by(ChatMessage.time)
    if since:
        query = query.find(ChatMessage.time > since)

    return request.formatter({ 'chatMessages': { 'chatMessage': [ msg.responsize() for msg in query ] }})
Example #37
0
def old_search():
    artist, album, title, anyf, count, offset, newer_than = map(request.values.get, [ 'artist', 'album', 'title', 'any', 'count', 'offset', 'newerThan' ])
    try:
        count = int(count) if count else 20
        offset = int(offset) if offset else 0
        newer_than = int(newer_than) / 1000 if newer_than else 0
    except:
        return request.error_formatter(0, 'Invalid parameter')

    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)
    elif album:
        query = store.find(Folder, Track.folder_id == Folder.id, Folder.name.contains_string(album), Folder.created > min_date).config(distinct = True)
    elif title:
        query = store.find(Track, Track.title.contains_string(title), Track.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])

        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] ]
    }})
Example #38
0
def lyrics():
    artist, title = map(request.values.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 = store.find(Track, Album.id == Track.album_id,
                       Artist.id == Album.artist_id, Track.title.like(title),
                       Artist.name.like(artist))
    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))
Example #39
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() })
Example #40
0
def rand_songs():
    size = request.values.get('size', '10')
    genre, fromYear, toYear, musicFolderId = map(request.values.get, [ 'genre', 'fromYear', 'toYear', 'musicFolderId' ])

    try:
        size = int(size) if size else 10
        fromYear = int(fromYear) if fromYear else None
        toYear = int(toYear) if toYear else None
        fid = uuid.UUID(musicFolderId) if musicFolderId else None
    except:
        return request.error_formatter(0, 'Invalid parameter format')

    query = store.find(Track)
    if fromYear:
        query = query.find(Track.year >= fromYear)
    if toYear:
        query = query.find(Track.year <= toYear)
    if genre:
        query = query.find(Track.genre == genre)
    if fid:
        if not store.find(Folder, Folder.id == fid, Folder.root == True).one():
            return request.error_formatter(70, 'Unknown folder')

        query = query.find(Track.root_folder_id == fid)

    count = query.count()
    if not count:
        return request.formatter({ 'randomSongs': {} })

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

    return request.formatter({
        'randomSongs': {
            'song': [ t.as_subsonic_child(request.user, request.prefs) for t in tracks ]
        }
    })
Example #41
0
def rand_songs():
    size = request.values.get('size', '10')
    genre, fromYear, toYear, musicFolderId = map(request.values.get, [ 'genre', 'fromYear', 'toYear', 'musicFolderId' ])

    try:
        size = int(size) if size else 10
        fromYear = int(fromYear) if fromYear else None
        toYear = int(toYear) if toYear else None
        fid = uuid.UUID(musicFolderId) if musicFolderId else None
    except:
        return request.error_formatter(0, 'Invalid parameter format')

    query = store.find(Track)
    if fromYear:
        query = query.find(Track.year >= fromYear)
    if toYear:
        query = query.find(Track.year <= toYear)
    if genre:
        query = query.find(Track.genre == genre)
    if fid:
        if not store.find(Folder, Folder.id == fid, Folder.root == True).one():
            return request.error_formatter(70, 'Unknown folder')

        query = query.find(Track.root_folder_id == fid)

    count = query.count()
    if not count:
        return request.formatter({ 'randomSongs': {} })

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

    return request.formatter({
        'randomSongs': {
            'song': [ t.as_subsonic_child(request.user, request.prefs) for t in tracks ]
        }
    })
Example #42
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()})
Example #43
0
def rate():
	id, rating = map(request.values.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:
		store.find(RatingTrack, RatingTrack.user_id == request.user.id, RatingTrack.rated_id == uid).remove()
		store.find(RatingFolder, RatingFolder.user_id == request.user.id, RatingFolder.rated_id == uid).remove()
	else:
		rated = store.get(Track, uid)
		rating_ent = RatingTrack
		if not rated:
			rated = store.get(Folder, uid)
			rating_ent = RatingFolder
			if not rated:
				return request.error_formatter(70, 'Unknown id')

		rating_info = store.get(rating_ent, (request.user.id, uid))
		if rating_info:
			rating_info.rating = rating
		else:
			rating_info = rating_ent()
			rating_info.user_id = request.user.id
			rating_info.rated_id = uid
			rating_info.rating = rating
			store.add(rating_info)

	store.commit()
	return request.formatter({})
Example #44
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] ]
        }
    })
Example #45
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({})
Example #46
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({})
Example #47
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] ]
        }
    })
Example #48
0
def scan_folder(id = None):
	s = Scanner(store)
	if id is None:
		for folder in store.find(Folder, Folder.root == True):
			FolderManager.scan(store, folder.id, s)
	else:
		status = FolderManager.scan(store, id, s)
		if status != FolderManager.SUCCESS:
			flash(FolderManager.error_str(status))
			return redirect(url_for('folder_index'))

	added, deleted = s.stats()
	store.commit()

	flash('Added: %i artists, %i albums, %i tracks' % (added[0], added[1], added[2]))
	flash('Deleted: %i artists, %i albums, %i tracks' % (deleted[0], deleted[1], deleted[2]))
	return redirect(url_for('folder_index'))
Example #49
0
def scan_folder(id = None):
	scanner = Scanner(store)
	if id is None:
		for folder in store.find(Folder, Folder.root == True):
			scanner.scan(folder)
	else:
		status, folder = FolderManager.get(store, id)
		if status != FolderManager.SUCCESS:
			flash(FolderManager.error_str(status))
			return redirect(url_for('folder_index'))
		scanner.scan(folder)

	scanner.finish()
	added, deleted = scanner.stats()
	store.commit()

	flash('Added: %i artists, %i albums, %i tracks' % (added[0], added[1], added[2]))
	flash('Deleted: %i artists, %i albums, %i tracks' % (deleted[0], deleted[1], deleted[2]))
	return redirect(url_for('folder_index'))
Example #50
0
def scan_folder(id=None):
    scanner = Scanner(store)
    if id is None:
        for folder in store.find(Folder, Folder.root == True):
            scanner.scan(folder)
    else:
        status, folder = FolderManager.get(store, id)
        if status != FolderManager.SUCCESS:
            flash(FolderManager.error_str(status))
            return redirect(url_for("folder_index"))
        scanner.scan(folder)

    scanner.finish()
    added, deleted = scanner.stats()
    store.commit()

    flash("Added: %i artists, %i albums, %i tracks" % (added[0], added[1], added[2]))
    flash("Deleted: %i artists, %i albums, %i tracks" % (deleted[0], deleted[1], deleted[2]))
    return redirect(url_for("folder_index"))
Example #51
0
def lyrics():
	artist, title = map(request.values.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 = store.find(Track, Album.id == Track.album_id, Artist.id == Album.artist_id, Track.title.like(title), Artist.name.like(artist))
	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))
Example #52
0
def list_artists():
	# According to the API page, there are no parameters?
	indexes = {}
	for artist in store.find(Artist):
		index = artist.name[0].upper() if artist.name else '?'
		if index in map(str, xrange(10)):
			index = '#'
		elif index not in string.letters:
			index = '?'

		if index not in indexes:
			indexes[index] = []

		indexes[index].append(artist)

	return request.formatter({
		'artists': {
			'index': [ {
				'name': k,
				'artist': [ a.as_subsonic_artist(request.user) for a in sorted(v, key = lambda a: a.name.lower()) ]
			} for k, v in sorted(indexes.iteritems()) ]
		}
	})
Example #53
0
def upload_file():
    if request.method == 'POST':
        file = request.files['file']
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
        #return redirect(url_for('uploaded_file', filename=filename))
            playlist = Playlist()
            playlist.user_id = uuid.UUID(session.get('userid'))
            playlist.name = filename
            store.add(playlist)
            tracks = []
            with open(os.path.join(app.config['UPLOAD_FOLDER'], filename)) as f:
                for line in f:
                    if line[0] != '#':
                        line = line.rstrip()
                        line = line.decode('utf-8')
                        tracks.append(line)
                        track = store.find(Track, Track.path == line).one()
                        if track:
                            playlist.tracks.add(track)
            store.commit()
            return render_template('upload.html', tracks = tracks)
    return '''
Example #54
0
def playlist_index():
	return render_template('playlists.html', mine = store.find(Playlist, Playlist.user_id == uuid.UUID(session.get('userid'))),
		others = store.find(Playlist, Playlist.user_id != uuid.UUID(session.get('userid'))))
Example #55
0
def list_indexes():
    musicFolderId = request.args.get('musicFolderId')
    ifModifiedSince = request.args.get('ifModifiedSince')
    if ifModifiedSince:
        try:
            ifModifiedSince = int(ifModifiedSince) / 1000
        except:
            return request.error_formatter(0, 'Invalid timestamp')

    if musicFolderId is None:
        folder = store.find(Folder, Folder.root == True)
    else:
        try:
            mfid = uuid.UUID(musicFolderId)
        except:
            return request.error_formatter(0, 'Invalid id')

        folder = store.get(Folder, mfid)

    if not folder or (type(folder) is Folder and not folder.root):
        return request.error_formatter(70, 'Folder not found')

    last_modif = max(
        map(lambda f: f.last_scan,
            folder)) if type(folder) is not Folder else folder.last_scan

    if (not ifModifiedSince is None) and last_modif < ifModifiedSince:
        return request.formatter(
            {'indexes': {
                'lastModified': last_modif * 1000
            }})

    # The XSD lies, we don't return artists but a directory structure
    if type(folder) is not Folder:
        artists = []
        childs = []
        for f in folder:
            artists += f.children
            childs += f.tracks
    else:
        artists = folder.children
        childs = folder.tracks

    indexes = {}
    for artist in artists:
        index = artist.name[0].upper()
        if index in map(str, xrange(10)):
            index = '#'
        elif index not in string.letters:
            index = '?'

        if index not in indexes:
            indexes[index] = []

        indexes[index].append(artist)

    return request.formatter({
        'indexes': {
            'lastModified':
            last_modif * 1000,
            'index': [{
                'name':
                k,
                'artist': [{
                    'id': str(a.id),
                    'name': a.name
                } for a in sorted(v, key=lambda a: a.name.lower())]
            } for k, v in sorted(indexes.iteritems())],
            'child': [
                c.as_subsonic_child(request.user)
                for c in sorted(childs, key=lambda t: t.sort_key())
            ]
        }
    })
Example #56
0
def playlist_index():
    return render_template(
        'playlists.html',
        mine=store.find(Playlist, Playlist.user_id == request.user.id),
        others=store.find(Playlist, Playlist.user_id != request.user.id,
                          Playlist.public == True))
Example #57
0
def old_search():
    artist, album, title, anyf, count, offset, newer_than = map(
        request.values.get,
        ['artist', 'album', 'title', 'any', 'count', 'offset', 'newerThan'])
    try:
        count = int(count) if count else 20
        offset = int(offset) if offset else 0
        newer_than = int(newer_than) / 1000 if newer_than else 0
    except:
        return request.error_formatter(0, 'Invalid parameter')

    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)
    elif album:
        query = store.find(Folder, Track.folder_id == Folder.id,
                           Folder.name.contains_string(album),
                           Folder.created > min_date).config(distinct=True)
    elif title:
        query = store.find(Track, Track.title.contains_string(title),
                           Track.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])

        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]
            ]
        }
    })
Example #58
0
def user_index():
    return render_template('users.html', users = store.find(User))
Example #59
0
def user_profile(uid, user):
    prefs = store.find(ClientPrefs, ClientPrefs.user_id == user.id)
    return render_template('profile.html', user = user, has_lastfm = app.config['LASTFM']['api_key'] != None, clients = prefs)