1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-11-10 04:02:17 +00:00

LastFM support

This commit is contained in:
Alban 2012-11-23 17:13:25 +01:00 committed by Alban
parent f5f1382c44
commit c255d9be99
4 changed files with 123 additions and 32 deletions

View File

@ -1,11 +1,14 @@
# coding: utf-8 # coding: utf-8
from flask import request, send_file from flask import request, send_file
import Image
from web import app
from db import Track, Folder
import config
import os.path, uuid import os.path, uuid
import Image
from time import time as now
import config
from web import app
from db import Track, Folder, User
from lastfm import LastFm
@app.route('/rest/stream.view', methods = [ 'GET', 'POST' ]) @app.route('/rest/stream.view', methods = [ 'GET', 'POST' ])
def stream_media(): def stream_media():
@ -78,3 +81,34 @@ def cover_art():
im.save(path, 'JPEG') im.save(path, 'JPEG')
return send_file(path) return send_file(path)
@app.route('/rest/scrobble.view', methods = [ 'GET', 'POST' ])
def scrobble():
tid, time, submission, u = map(request.args.get, [ 'id', 'time', 'submission', 'u' ])
if not tid:
return request.error_formatter(10, 'Missing file id')
try:
tid = uuid.UUID(tid)
except:
return request.error_formatter(0, 'Invalid file id')
track = Track.query.get(tid)
if not track:
return request.error_formatter(70, 'File not found')
if time:
try:
time = int(time) / 1000
except:
return request.error_formatter(0, 'Invalid time value')
else:
time = int(now())
user = User.query.filter(User.name == u).one()
lfm = LastFm(user, app.logger)
if submission in (None, '', True, 'true', 'True', 1, '1'):
lfm.scrobble(track, time)
else:
lfm.now_playing(track)
return request.formatter({})

View File

@ -18,7 +18,7 @@ def user_info():
'user': { 'user': {
'username': user.name, 'username': user.name,
'email': user.mail, 'email': user.mail,
'scrobblingEnabled': False, 'scrobblingEnabled': user.lastfm_session is not None and user.lastfm_status,
'adminRole': user.admin, 'adminRole': user.admin,
'settingsRole': False, 'settingsRole': False,
'downloadRole': False, 'downloadRole': False,

78
lastfm.py Executable file
View File

@ -0,0 +1,78 @@
# coding: utf-8
import requests, hashlib
import config
from db import session
class LastFm:
def __init__(self, user, logger):
self.__user = user
self.__api_key = config.get('LASTFM_KEY')
self.__api_secret = config.get('LASTFM_SECRET')
self.__enabled = self.__api_key is not None
self.__logger = logger
def link_account(self, token):
if not self.__enabled:
return False, 'No API key set'
res = self.__api_request(False, method = 'auth.getSession', token = token)
if 'error' in res:
return False, 'Error %i: %s' % (res['error'], res['message'])
else:
self.__user.lastfm_session = res['session']['key']
self.__user.lastfm_status = True
session.commit()
return True, 'OK'
def unlink_account(self):
self.__user.lastfm_session = None
self.__user.lastfm_status = True
session.commit()
def now_playing(self, track):
if not self.__enabled:
return
res = self.__api_request(True, method = 'track.updateNowPlaying', artist = track.album.artist.name, track = track.title, album = track.album.name,
trackNumber = track.number, duration = track.duration)
def scrobble(self, track, ts):
if not self.__enabled:
return
res = self.__api_request(True, method = 'track.scrobble', artist = track.album.artist.name, track = track.title, album = track.album.name,
timestamp = ts, trackNumber = track.number, duration = track.duration)
def __api_request(self, write, **kwargs):
if not self.__enabled:
return
if write:
if not self.__user.lastfm_session or not self.__user.lastfm_status:
return
kwargs['sk'] = self.__user.lastfm_session
kwargs['api_key'] = self.__api_key
sig_str = ''
for k, v in sorted(kwargs.iteritems()):
sig_str += k + str(v)
sig = hashlib.md5(sig_str + self.__api_secret).hexdigest()
kwargs['api_sig'] = sig
kwargs['format'] = 'json'
if write:
r = requests.post('http://ws.audioscrobbler.com/2.0/', data = kwargs)
else:
r = requests.get('http://ws.audioscrobbler.com/2.0/', params = kwargs)
if 'error' in r.json:
if r.json['error'] in (9, '9'):
self.__user.lastfm_status = False
session.commit()
self.__logger.warn('LastFM error %i: %s' % (r.json['error'], r.json['message']))
return r.json

33
user.py
View File

@ -1,12 +1,12 @@
# coding: utf-8 # coding: utf-8
from flask import request, session, flash, render_template, redirect, url_for from flask import request, session, flash, render_template, redirect, url_for
import requests, hashlib
from web import app from web import app
from user_manager import UserManager from user_manager import UserManager
from db import User, session as db_sess from db import User, session as db_sess
import config import config
from lastfm import LastFm
@app.before_request @app.before_request
def check_admin(): def check_admin():
@ -114,37 +114,16 @@ def lastfm_reg():
flash('Missing LastFM auth token') flash('Missing LastFM auth token')
return redirect(url_for('user_profile')) return redirect(url_for('user_profile'))
p = { lfm = LastFm(UserManager.get(session.get('userid'))[1], app.logger)
'api_key': config.get('LASTFM_KEY'), status, error = lfm.link_account(token)
'method': 'auth.getSession', flash(error if not status else 'Successfully linked LastFM account')
'token': token
}
sig_str = ''
for k, v in sorted(p.iteritems()):
sig_str += k + v
sig = hashlib.md5(sig_str + config.get('LASTFM_SECRET')).hexdigest()
p['api_sig'] = sig
p['format'] = 'json'
r = requests.get('http://ws.audioscrobbler.com/2.0/', params = p)
if 'error' in r.json:
flash('Error %i: %s' % (r.json['error'], r.json['message']))
else:
user = UserManager.get(session.get('userid'))[1]
user.lastfm_session = r.json['session']['key']
user.lastfm_status = True
db_sess.commit()
flash('Successfully linked LastFM account')
return redirect(url_for('user_profile')) return redirect(url_for('user_profile'))
@app.route('/user/lastfm/unlink') @app.route('/user/lastfm/unlink')
def lastfm_unreg(): def lastfm_unreg():
user = UserManager.get(session.get('userid'))[1] lfm = LastFm(UserManager.get(session.get('userid'))[1], app.logger)
user.lastfm_session = None lfm.unlink_account()
user.lastfm_status = True
db_sess.commit()
flash('Unliked LastFM account') flash('Unliked LastFM account')
return redirect(url_for('user_profile')) return redirect(url_for('user_profile'))