mirror of
https://github.com/spl0k/supysonic.git
synced 2024-11-09 19:52:16 +00:00
LastFM support
This commit is contained in:
parent
f5f1382c44
commit
c255d9be99
42
api/media.py
42
api/media.py
@ -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({})
|
||||||
|
|
||||||
|
@ -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
78
lastfm.py
Executable 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
33
user.py
@ -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'))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user