2019-05-05 12:56:09 +03:00
|
|
|
import urllib.parse, urllib.request
|
|
|
|
import json
|
2019-05-10 14:15:40 +03:00
|
|
|
import base64
|
2019-05-05 12:56:09 +03:00
|
|
|
from doreah.settings import get_settings
|
|
|
|
from doreah.logging import log
|
2019-06-24 16:43:38 +03:00
|
|
|
import hashlib
|
2019-06-24 17:09:25 +03:00
|
|
|
import xml.etree.ElementTree as ET
|
2019-06-24 16:43:38 +03:00
|
|
|
|
|
|
|
### PICTURES
|
2019-05-05 12:56:09 +03:00
|
|
|
|
|
|
|
|
2019-05-23 14:45:19 +03:00
|
|
|
apis_artists = []
|
|
|
|
|
|
|
|
if get_settings("LASTFM_API_KEY") not in [None,"ASK"] and get_settings("FANARTTV_API_KEY") not in [None,"ASK"]:
|
|
|
|
apis_artists.append({
|
2019-05-05 12:56:09 +03:00
|
|
|
"name":"LastFM + Fanart.tv",
|
2019-05-23 14:45:19 +03:00
|
|
|
#"check":get_settings("LASTFM_API_KEY") not in [None,"ASK"] and get_settings("FANARTTV_API_KEY") not in [None,"ASK"],
|
2019-05-05 12:56:09 +03:00
|
|
|
"steps":[
|
2019-05-23 14:45:19 +03:00
|
|
|
("get","http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist={artiststring}&api_key=" + str(get_settings("LASTFM_API_KEY")) + "&format=json"),
|
2019-05-05 12:56:09 +03:00
|
|
|
("parse",["artist","mbid"]),
|
2019-05-23 14:45:19 +03:00
|
|
|
("get","http://webservice.fanart.tv/v3/music/{var}?api_key=" + str(get_settings("FANARTTV_API_KEY"))),
|
2019-05-05 12:56:09 +03:00
|
|
|
("parse",["artistthumb",0,"url"])
|
|
|
|
]
|
2019-05-23 14:45:19 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
if get_settings("SPOTIFY_API_ID") not in [None,"ASK"] and get_settings("SPOTIFY_API_SECRET") not in [None,"ASK"]:
|
|
|
|
apis_artists.append({
|
2019-05-10 14:15:40 +03:00
|
|
|
"name":"Spotify",
|
2019-05-23 14:45:19 +03:00
|
|
|
#"check":get_settings("SPOTIFY_API_ID") not in [None,"ASK"] and get_settings("SPOTIFY_API_SECRET") not in [None,"ASK"],
|
2019-05-10 14:15:40 +03:00
|
|
|
"steps":[
|
|
|
|
("post","https://accounts.spotify.com/api/token",{"Authorization":"Basic " + base64.b64encode(bytes(get_settings("SPOTIFY_API_ID") + ":" + get_settings("SPOTIFY_API_SECRET"),encoding="utf-8")).decode("utf-8")},{"grant_type":"client_credentials"}),
|
|
|
|
("parse",["access_token"]),
|
|
|
|
("get","https://api.spotify.com/v1/search?q={artiststring}&type=artist&access_token={var}"),
|
|
|
|
("parse",["artists","items",0,"images",0,"url"])
|
|
|
|
]
|
2019-05-23 14:45:19 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
apis_tracks = []
|
2019-05-05 12:56:09 +03:00
|
|
|
|
2019-05-23 14:45:19 +03:00
|
|
|
if get_settings("LASTFM_API_KEY") not in [None,"ASK"]:
|
|
|
|
apis_tracks.append({
|
2019-05-05 12:56:09 +03:00
|
|
|
"name":"LastFM",
|
2019-05-23 14:45:19 +03:00
|
|
|
#"check":get_settings("LASTFM_API_KEY") not in [None,"ASK"],
|
2019-05-05 12:56:09 +03:00
|
|
|
"steps":[
|
2019-05-10 14:15:40 +03:00
|
|
|
("get","https://ws.audioscrobbler.com/2.0/?method=track.getinfo&track={titlestring}&artist={artiststring}&api_key=" + get_settings("LASTFM_API_KEY") + "&format=json"),
|
2019-05-05 12:56:09 +03:00
|
|
|
("parse",["track","album","image",3,"#text"])
|
|
|
|
]
|
2019-05-23 14:45:19 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
if get_settings("SPOTIFY_API_ID") not in [None,"ASK"] and get_settings("SPOTIFY_API_SECRET") not in [None,"ASK"]:
|
|
|
|
apis_tracks.append({
|
2019-05-10 14:15:40 +03:00
|
|
|
"name":"Spotify",
|
2019-05-23 14:45:19 +03:00
|
|
|
#"check":get_settings("SPOTIFY_API_ID") not in [None,"ASK"] and get_settings("SPOTIFY_API_SECRET") not in [None,"ASK"],
|
2019-05-10 14:15:40 +03:00
|
|
|
"steps":[
|
|
|
|
("post","https://accounts.spotify.com/api/token",{"Authorization":"Basic " + base64.b64encode(bytes(get_settings("SPOTIFY_API_ID") + ":" + get_settings("SPOTIFY_API_SECRET"),encoding="utf-8")).decode("utf-8")},{"grant_type":"client_credentials"}),
|
|
|
|
("parse",["access_token"]),
|
|
|
|
("get","https://api.spotify.com/v1/search?q={artiststring}%20{titlestring}&type=track&access_token={var}"),
|
|
|
|
("parse",["tracks","items",0,"album","images",0,"url"])
|
|
|
|
]
|
2019-05-23 14:45:19 +03:00
|
|
|
})
|
|
|
|
|
2019-05-05 12:56:09 +03:00
|
|
|
|
|
|
|
def api_request_artist(artist):
|
|
|
|
for api in apis_artists:
|
2019-05-23 14:45:19 +03:00
|
|
|
if True:
|
2019-05-05 12:56:09 +03:00
|
|
|
log("API: " + api["name"] + "; Image request: " + artist,module="external")
|
|
|
|
try:
|
|
|
|
artiststring = urllib.parse.quote(artist)
|
|
|
|
var = artiststring
|
|
|
|
for step in api["steps"]:
|
2019-05-10 14:15:40 +03:00
|
|
|
if step[0] == "get":
|
2019-05-05 12:56:09 +03:00
|
|
|
response = urllib.request.urlopen(step[1].format(artiststring=artiststring,var=var))
|
|
|
|
var = json.loads(response.read())
|
2019-05-10 14:15:40 +03:00
|
|
|
elif step[0] == "post":
|
|
|
|
keys = {
|
|
|
|
"url":step[1].format(artiststring=artiststring,var=var),
|
|
|
|
"method":"POST",
|
|
|
|
"headers":step[2],
|
|
|
|
"data":bytes(urllib.parse.urlencode(step[3]),encoding="utf-8")
|
|
|
|
}
|
|
|
|
req = urllib.request.Request(**keys)
|
|
|
|
response = urllib.request.urlopen(req)
|
|
|
|
var = json.loads(response.read())
|
2019-05-05 12:56:09 +03:00
|
|
|
elif step[0] == "parse":
|
|
|
|
for node in step[1]:
|
|
|
|
var = var[node]
|
|
|
|
assert isinstance(var,str) and var != ""
|
|
|
|
except:
|
|
|
|
continue
|
|
|
|
|
|
|
|
return var
|
|
|
|
else:
|
|
|
|
pass
|
|
|
|
return None
|
|
|
|
|
|
|
|
def api_request_track(track):
|
|
|
|
artists, title = track
|
|
|
|
for api in apis_tracks:
|
2019-05-23 14:45:19 +03:00
|
|
|
if True:
|
2019-05-05 12:56:09 +03:00
|
|
|
log("API: " + api["name"] + "; Image request: " + "/".join(artists) + " - " + title,module="external")
|
|
|
|
try:
|
|
|
|
artiststring = urllib.parse.quote(", ".join(artists))
|
|
|
|
titlestring = urllib.parse.quote(title)
|
|
|
|
var = artiststring + titlestring
|
|
|
|
for step in api["steps"]:
|
2019-05-10 14:15:40 +03:00
|
|
|
if step[0] == "get":
|
2019-05-05 12:56:09 +03:00
|
|
|
response = urllib.request.urlopen(step[1].format(artiststring=artiststring,titlestring=titlestring,var=var))
|
|
|
|
var = json.loads(response.read())
|
2019-05-10 14:15:40 +03:00
|
|
|
elif step[0] == "post":
|
|
|
|
keys = {
|
|
|
|
"url":step[1].format(artiststring=artiststring,titlestring=titlestring,var=var),
|
|
|
|
"method":"POST",
|
|
|
|
"headers":step[2],
|
|
|
|
"data":bytes(urllib.parse.urlencode(step[3]),encoding="utf-8")
|
|
|
|
}
|
|
|
|
req = urllib.request.Request(**keys)
|
|
|
|
response = urllib.request.urlopen(req)
|
|
|
|
var = json.loads(response.read())
|
2019-05-05 12:56:09 +03:00
|
|
|
elif step[0] == "parse":
|
|
|
|
for node in step[1]:
|
|
|
|
var = var[node]
|
|
|
|
assert isinstance(var,str) and var != ""
|
|
|
|
except:
|
2019-05-10 14:15:40 +03:00
|
|
|
if len(artists) != 1:
|
|
|
|
# try the same track with every single artist
|
|
|
|
for a in artists:
|
|
|
|
result = api_request_track(([a],title))
|
|
|
|
if result is not None:
|
|
|
|
return result
|
2019-05-05 12:56:09 +03:00
|
|
|
continue
|
|
|
|
|
|
|
|
return var
|
|
|
|
else:
|
|
|
|
pass
|
|
|
|
|
|
|
|
return None
|
2019-06-24 16:43:38 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### SCROBBLING
|
|
|
|
|
|
|
|
# creates signature and returns full query string
|
|
|
|
def lfmbuild(parameters):
|
|
|
|
m = hashlib.md5()
|
|
|
|
keys = sorted(str(k) for k in parameters)
|
|
|
|
m.update(utf("".join(str(k) + str(parameters[k]) for k in keys)))
|
|
|
|
m.update(utf(get_settings("LASTFM_API_SECRET")))
|
|
|
|
sig = m.hexdigest()
|
2019-06-24 18:23:27 +03:00
|
|
|
return urllib.parse.urlencode(parameters) + "&api_sig=" + sig
|
2019-06-24 16:43:38 +03:00
|
|
|
|
|
|
|
def utf(st):
|
|
|
|
return st.encode(encoding="UTF-8")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
apis_scrobble = []
|
|
|
|
|
|
|
|
if get_settings("LASTFM_API_SK") not in [None,"ASK"] and get_settings("LASTFM_API_SECRET") not in [None,"ASK"] and get_settings("LASTFM_API_KEY") not in [None,"ASK"]:
|
|
|
|
apis_scrobble.append({
|
|
|
|
"name":"LastFM",
|
|
|
|
"scrobbleurl":"http://ws.audioscrobbler.com/2.0/",
|
|
|
|
"requestbody":lambda artists,title,timestamp: lfmbuild({"method":"track.scrobble","artist[0]":", ".join(artists),"track[0]":title,"timestamp":timestamp,"api_key":get_settings("LASTFM_API_KEY"),"sk":get_settings("LASTFM_API_SK")})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def proxy_scrobble(artists,title,timestamp):
|
|
|
|
for api in apis_scrobble:
|
|
|
|
response = urllib.request.urlopen(api["scrobbleurl"],data=utf(api["requestbody"](artists,title,timestamp)))
|
|
|
|
xml = response.read()
|
2019-06-24 17:09:25 +03:00
|
|
|
data = ET.fromstring(xml)
|
|
|
|
if data.attrib.get("status") == "ok":
|
|
|
|
if data.find("scrobbles").attrib.get("ignored") == "0":
|
|
|
|
log(api["name"] + ": Scrobble accepted: " + "/".join(artists) + " - " + title)
|
|
|
|
else:
|
|
|
|
log(api["name"] + ": Scrobble not accepted: " + "/".join(artists) + " - " + title)
|