2020-09-03 03:57:51 +03:00
|
|
|
from ._base import APIHandler
|
|
|
|
from ._exceptions import *
|
|
|
|
from .. import database
|
|
|
|
import datetime
|
2022-04-06 23:05:41 +03:00
|
|
|
from ._apikeys import apikeystore
|
2020-09-03 03:57:51 +03:00
|
|
|
|
2022-04-09 22:39:04 +03:00
|
|
|
from ..pkg_global.conf import malojaconfig
|
2021-11-12 19:23:55 +03:00
|
|
|
|
2020-09-03 03:57:51 +03:00
|
|
|
|
|
|
|
class Listenbrainz(APIHandler):
|
|
|
|
__apiname__ = "Listenbrainz"
|
|
|
|
__doclink__ = "https://listenbrainz.readthedocs.io/en/production/"
|
2020-09-04 01:08:24 +03:00
|
|
|
__aliases__ = [
|
|
|
|
"listenbrainz/1",
|
|
|
|
"lbrnz/1"
|
|
|
|
]
|
2020-09-03 03:57:51 +03:00
|
|
|
|
|
|
|
def init(self):
|
|
|
|
self.methods = {
|
|
|
|
"submit-listens":self.submit,
|
|
|
|
"validate-token":self.validate_token
|
|
|
|
}
|
|
|
|
self.errors = {
|
|
|
|
BadAuthException:(401,{"code":401,"error":"You need to provide an Authorization header."}),
|
|
|
|
InvalidAuthException:(401,{"code":401,"error":"Incorrect Authorization"}),
|
|
|
|
InvalidMethodException:(200,{"code":200,"error":"Invalid Method"}),
|
|
|
|
MalformedJSONException:(400,{"code":400,"error":"Invalid JSON document submitted."}),
|
|
|
|
ScrobblingException:(500,{"code":500,"error":"Unspecified server error."})
|
|
|
|
}
|
|
|
|
|
|
|
|
def get_method(self,pathnodes,keys):
|
|
|
|
return pathnodes.pop(0)
|
|
|
|
|
|
|
|
def submit(self,pathnodes,keys):
|
|
|
|
try:
|
2021-11-12 19:16:59 +03:00
|
|
|
token = self.get_token_from_request_keys(keys)
|
2022-04-24 20:41:55 +03:00
|
|
|
except Exception:
|
2020-09-03 03:57:51 +03:00
|
|
|
raise BadAuthException()
|
|
|
|
|
2022-04-06 23:05:41 +03:00
|
|
|
client = apikeystore.check_and_identify_key(token)
|
|
|
|
|
|
|
|
if not client:
|
2020-09-03 03:57:51 +03:00
|
|
|
raise InvalidAuthException()
|
|
|
|
|
|
|
|
try:
|
|
|
|
listentype = keys["listen_type"]
|
|
|
|
payload = keys["payload"]
|
2022-04-24 20:41:55 +03:00
|
|
|
except Exception:
|
2020-09-07 21:26:23 +03:00
|
|
|
raise MalformedJSONException()
|
|
|
|
|
|
|
|
if listentype == "playing_now":
|
|
|
|
return 200,{"status":"ok"}
|
|
|
|
elif listentype in ["single","import"]:
|
|
|
|
for listen in payload:
|
|
|
|
try:
|
2020-09-03 03:57:51 +03:00
|
|
|
metadata = listen["track_metadata"]
|
2022-06-06 19:02:34 +03:00
|
|
|
artiststr, titlestr = metadata["artist_name"], metadata["track_name"]
|
|
|
|
albumstr = metadata.get("release_name")
|
2022-05-17 17:34:09 +03:00
|
|
|
additional = metadata.get("additional_info",{})
|
2020-09-03 03:57:51 +03:00
|
|
|
try:
|
|
|
|
timestamp = int(listen["listened_at"])
|
2022-04-24 20:41:55 +03:00
|
|
|
except Exception:
|
2020-09-04 00:42:27 +03:00
|
|
|
timestamp = None
|
2022-04-24 20:41:55 +03:00
|
|
|
except Exception:
|
2020-09-07 21:26:23 +03:00
|
|
|
raise MalformedJSONException()
|
2021-11-12 19:16:59 +03:00
|
|
|
|
2022-05-17 17:34:09 +03:00
|
|
|
extrafields = {
|
|
|
|
# fields that will not be consumed by regular scrobbling
|
|
|
|
# will go into 'extra'
|
|
|
|
k:additional[k]
|
2022-07-15 18:18:22 +03:00
|
|
|
for k in ['track_mbid', 'release_mbid', 'release_artist_name', 'artist_mbids','recording_mbid','tags', 'origin_url', 'spotify_id', 'music_service', 'music_service_name', 'submission_client']
|
2022-05-17 17:34:09 +03:00
|
|
|
if k in additional
|
|
|
|
}
|
|
|
|
|
2022-04-06 23:05:41 +03:00
|
|
|
self.scrobble({
|
|
|
|
'track_artists':[artiststr],
|
|
|
|
'track_title':titlestr,
|
2022-06-04 10:31:18 +03:00
|
|
|
'album_name':albumstr,
|
2022-05-17 17:34:09 +03:00
|
|
|
'scrobble_time':timestamp,
|
2022-09-11 21:58:37 +03:00
|
|
|
'track_length': additional.get("duration"),
|
2022-05-17 17:34:09 +03:00
|
|
|
**extrafields
|
2022-04-06 23:05:41 +03:00
|
|
|
},client=client)
|
2020-09-05 17:59:25 +03:00
|
|
|
|
|
|
|
return 200,{"status":"ok"}
|
2020-09-03 03:57:51 +03:00
|
|
|
|
2020-09-07 21:26:23 +03:00
|
|
|
|
2020-09-03 03:57:51 +03:00
|
|
|
def validate_token(self,pathnodes,keys):
|
|
|
|
try:
|
2021-11-12 19:16:59 +03:00
|
|
|
token = self.get_token_from_request_keys(keys)
|
2022-04-24 20:41:55 +03:00
|
|
|
except Exception:
|
2020-09-03 03:57:51 +03:00
|
|
|
raise BadAuthException()
|
2022-04-06 23:46:43 +03:00
|
|
|
if not apikeystore.check_key(token):
|
2020-09-03 03:57:51 +03:00
|
|
|
raise InvalidAuthException()
|
|
|
|
else:
|
2021-12-19 23:10:55 +03:00
|
|
|
return 200,{"code":200,"message":"Token valid.","valid":True,"user_name":malojaconfig["NAME"]}
|
2021-11-12 19:16:59 +03:00
|
|
|
|
|
|
|
def get_token_from_request_keys(self,keys):
|
|
|
|
if 'token' in keys:
|
|
|
|
return keys.get("token").strip()
|
|
|
|
if 'Authorization' in keys:
|
|
|
|
auth = keys.get("Authorization")
|
|
|
|
if auth.startswith('token '):
|
|
|
|
return auth.replace("token ","",1).strip()
|
|
|
|
if auth.startswith('Token '):
|
|
|
|
return auth.replace("Token ","",1).strip()
|
|
|
|
raise BadAuthException()
|