From 1caf274020088600565797b4a32e8bcb9f61978b Mon Sep 17 00:00:00 2001 From: Krateng Date: Sun, 5 May 2019 11:56:09 +0200 Subject: [PATCH] Adjusted API due to Last.FM's recent changes, made additions easier --- external.py | 84 ++++++++++++++++++++ rules/predefined/krateng_kpopgirlgroups.tsv | 5 ++ settings/default.ini | 1 + utilities.py | 85 +++------------------ 4 files changed, 99 insertions(+), 76 deletions(-) create mode 100644 external.py diff --git a/external.py b/external.py new file mode 100644 index 0000000..853d1a7 --- /dev/null +++ b/external.py @@ -0,0 +1,84 @@ +import urllib.parse, urllib.request +import json +from doreah.settings import get_settings +from doreah.logging import log + + +apis_artists = [ + { + "name":"LastFM + Fanart.tv", + "check":get_settings("LASTFM_API_KEY") is not None and get_settings("FANARTTV_API_KEY") is not None, + "steps":[ + ("url","http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist={artiststring}&api_key=" + get_settings("LASTFM_API_KEY") + "&format=json"), + ("parse",["artist","mbid"]), + ("url","http://webservice.fanart.tv/v3/music/{var}?api_key=" + get_settings("FANARTTV_API_KEY")), + ("parse",["artistthumb",0,"url"]) + ] + } +] + +apis_tracks = [ + { + "name":"LastFM", + "check":get_settings("LASTFM_API_KEY") is not None, + "steps":[ + ("url","https://ws.audioscrobbler.com/2.0/?method=track.getinfo&track={titlestring}&artist={artiststring}&api_key=" + get_settings("LASTFM_API_KEY") + "&format=json"), + ("parse",["track","album","image",3,"#text"]) + ] + } +] + +def api_request_artist(artist): + for api in apis_artists: + if api["check"]: + log("API: " + api["name"] + "; Image request: " + artist,module="external") + try: + artiststring = urllib.parse.quote(artist) + var = artiststring + for step in api["steps"]: + if step[0] == "url": + response = urllib.request.urlopen(step[1].format(artiststring=artiststring,var=var)) + var = json.loads(response.read()) + 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: + if api["check"]: + 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"]: + if step[0] == "url": + response = urllib.request.urlopen(step[1].format(artiststring=artiststring,titlestring=titlestring,var=var)) + var = json.loads(response.read()) + elif step[0] == "parse": + for node in step[1]: + var = var[node] + assert isinstance(var,str) and var != "" + except: + if len(artists) == 1: return None + # 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 + continue + + return var + else: + pass + + return None diff --git a/rules/predefined/krateng_kpopgirlgroups.tsv b/rules/predefined/krateng_kpopgirlgroups.tsv index 76a438c..e28a5a9 100644 --- a/rules/predefined/krateng_kpopgirlgroups.tsv +++ b/rules/predefined/krateng_kpopgirlgroups.tsv @@ -55,6 +55,7 @@ replaceartist 스텔라(Stellar) (Stellar) Stellar replacetitle 찔려 Sting Sting # Red Velvet +countas Seulgi Red Velvet replacetitle 러시안 룰렛 Russian Roulette Russian Roulette replacetitle 피카부 Peek-a-Boo Peek-A-Boo replacetitle 빨간 맛 Red Flavor Red Flavor @@ -130,3 +131,7 @@ replaceartist 소녀시대 Girls' Generation # Apink replaceartist A Pink Apink replaceartist A pink Apink + +# IOI +replaceartist CHUNG HA Chungha +countas Chungha I.O.I diff --git a/settings/default.ini b/settings/default.ini index 9356980..13f2f7f 100644 --- a/settings/default.ini +++ b/settings/default.ini @@ -6,6 +6,7 @@ API_PORT = 42011 [Third Party Services] LASTFM_API_KEY = "ASK" # "ASK" signifies that the user has not yet indicated to not use any key at all. +FANARTTV_API_KEY = "ASK" CACHE_EXPIRE_NEGATIVE = 30 # after how many days negative results should be tried again CACHE_EXPIRE_POSITIVE = 300 # after how many days positive results should be refreshed diff --git a/utilities.py b/utilities.py index 4748952..2b1b7e5 100644 --- a/utilities.py +++ b/utilities.py @@ -13,6 +13,8 @@ from doreah import caching from doreah.logging import log from doreah.regular import yearly, daily +from external import api_request_track, api_request_artist + ##### @@ -130,75 +132,6 @@ def consistentRulestate(folder,checksums): -def apirequest(artists=None,artist=None,title=None): - - import urllib.parse, urllib.request - import json - - #try: - #with open("apikey","r") as keyfile: - # apikey = keyfile.read().replace("\n","") - - apikey = settings.get_settings("LASTFM_API_KEY") - if apikey is None: return None - #except: - # return None - - - sites = [ - { - "name":"lastfm", - "artisturl":"https://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist={artist}&api_key=" + apikey + "&format=json", - "trackurl":"https://ws.audioscrobbler.com/2.0/?method=track.getinfo&track={title}&artist={artist}&api_key=" + apikey + "&format=json", - "result_artist_imgurl":lambda data:data["artist"]["image"][3]["#text"], - "result_track_imgurl":lambda data:data["track"]["album"]["image"][3]["#text"] - #"result_artist_desc":lambda data:data["artist"]["bio"]["summary"], - #"result_track_desc":lambda data:None - } - ] - - - # TRACKS - if title is not None: - for s in sites: - try: - artiststr = urllib.parse.quote(", ".join(artists)) - titlestr = urllib.parse.quote(title) - response = urllib.request.urlopen(s["trackurl"].format(artist=artiststr,title=titlestr)) - log("API: " + s["name"] + "; Image request: " + "/".join(artists) + " - " + title,module="external") - data = json.loads(response.read()) - if s["result_track_imgurl"](data) != "": - return s["result_track_imgurl"](data) - except: - pass - - if len(artists) == 1: - #return {"image":apirequest(artist=artists[0])["image"]} - return None - - # try the same track with every single artist - for a in artists: - rec = apirequest(artists=[a],title=title) - if rec is not None: - return rec - - return None - - # ARTISTS - else: - for s in sites: - try: - response = urllib.request.urlopen(s["artisturl"].format(artist=urllib.parse.quote(artist))) - log("API: " + s["name"] + "; Image request: " + artist,module="external") - data = json.loads(response.read()) - if s["result_artist_imgurl"](data) != "": - return s["result_artist_imgurl"](data) - except: - pass - - return None - - ### Caches @@ -294,7 +227,7 @@ def local_files(artist=None,artists=None,title=None): -# these caches are there so we don't check all files every thime, but return the same one +# these caches are there so we don't check all files every time, but return the same one local_cache_age = settings.get_settings("LOCAL_IMAGE_ROTATE") local_artist_cache = caching.Cache(maxage=local_cache_age) local_track_cache = caching.Cache(maxage=local_cache_age) @@ -350,15 +283,15 @@ def getTrackImage(artists,title,fast=False): pass # do we have an api key? - apikey = settings.get_settings("LASTFM_API_KEY") - if apikey is None: return "" # DO NOT CACHE THAT +# apikey = settings.get_settings("LASTFM_API_KEY") +# if apikey is None: return "" # DO NOT CACHE THAT # fast request only retuns cached and local results, generates redirect link for rest if fast: return "/image?title=" + urllib.parse.quote(title) + "&" + "&".join(["artist=" + urllib.parse.quote(a) for a in artists]) # non-fast lookup (esentially only the resolver lookup) - result = apirequest(artists=artists,title=title) + result = api_request_track((artists,title)) # cache results (even negative ones) #cachedTracks[(frozenset(artists),title)] = result @@ -420,8 +353,8 @@ def getArtistImage(artist,fast=False): # do we have an api key? - apikey = settings.get_settings("LASTFM_API_KEY") - if apikey is None: return "" # DO NOT CACHE THAT +# apikey = settings.get_settings("LASTFM_API_KEY") +# if apikey is None: return "" # DO NOT CACHE THAT @@ -429,7 +362,7 @@ def getArtistImage(artist,fast=False): if fast: return "/image?artist=" + urllib.parse.quote(artist) # non-fast lookup (esentially only the resolver lookup) - result = apirequest(artist=artist) + result = api_request_artist(artist=artist) # cache results (even negative ones) #cachedArtists[artist] = result