diff --git a/images/artists/.gitignore b/images/artists/.gitignore new file mode 100644 index 0000000..96960a0 --- /dev/null +++ b/images/artists/.gitignore @@ -0,0 +1,4 @@ +*.png +*.jpg +*.jpeg +!default.jpg diff --git a/images/artists/default.jpg b/images/artists/default.jpg new file mode 100644 index 0000000..0da19b2 Binary files /dev/null and b/images/artists/default.jpg differ diff --git a/images/tracks/.gitignore b/images/tracks/.gitignore new file mode 100644 index 0000000..96960a0 --- /dev/null +++ b/images/tracks/.gitignore @@ -0,0 +1,4 @@ +*.png +*.jpg +*.jpeg +!default.jpg diff --git a/server.py b/server.py index 0b4c862..c794b7c 100755 --- a/server.py +++ b/server.py @@ -72,11 +72,11 @@ def graceful_exit(sig=None,frame=None): sys.exit() -@webserver.route("/info/") -@webserver.route("/info/") -@webserver.route("/info/") +@webserver.route("/images/") +@webserver.route("/images/") +@webserver.route("/images/") def static_image(pth): - return static_file("info/" + pth,root="") + return static_file("images/" + pth,root="") @webserver.route("/") @webserver.route("/") diff --git a/utilities.py b/utilities.py index cdb674a..6108a43 100644 --- a/utilities.py +++ b/utilities.py @@ -144,88 +144,206 @@ def log(msg): ### Media info -def getArtistInfo(artist): +def apirequest(artists=None,artist=None,title=None): + + import urllib.parse, urllib.request + import json + + with open("apikey","r") as keyfile: + apikey = keyfile.read().replace("\n","") + + 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"][2]["#text"], + "result_track_imgurl":lambda data:data["track"]["album"]["image"][2]["#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)) + data = json.loads(response.read()) + if s["result_track_imgurl"](data) != "": + return {"image":s["result_track_imgurl"](data)} + except: + pass + + # if nothing worked, just return the artist image + if len(artists) == 1: + return {"image":apirequest(artist=artists[0])["image"]} + #return {"image":None,"desc":None} + + # try the same track with every single artist + for a in artists: + rec = apirequest(artists=[a],title=title) + if rec["image"] is not None: + return rec + + # ARTISTS + else: + for s in sites: + try: + response = urllib.request.urlopen(s["artisturl"].format(artist=urllib.parse.quote(artist))) + data = json.loads(response.read()) + if s["result_artist_imgurl"](data) != "": + return {"image":s["result_artist_imgurl"](data)} + except: + pass + + return {"image":None} + +cachedTracks = {} +cachedArtists = {} + +def getTrackInfo(artists,title): import re import os - import urllib - import json - import _thread - - filename = re.sub("[^a-zA-Z0-9]","",artist) - filepath = "info/artists/" + filename - filepath_cache = "info/artists_cache/" + filename + obj = (frozenset(artists),title) + filename = "-".join([re.sub("[^a-zA-Z0-9]","",artist) for artist in artists]) + "_" + re.sub("[^a-zA-Z0-9]","",title) + if filename = "": filename = str(hash(obj)) + filepath = "images/tracks/" + filename # check if custom image exists if os.path.exists(filepath + ".png"): imgurl = "/" + filepath + ".png" + return {"image":imgurl} elif os.path.exists(filepath + ".jpg"): imgurl = "/" + filepath + ".jpg" + return {"image":imgurl} elif os.path.exists(filepath + ".jpeg"): imgurl = "/" + filepath + ".jpeg" + return {"image":imgurl} + + try: + return {"image":cachedTracks[(frozenset(artists),title)]} + except: + pass + + result = apirequest(artists=artists,title=title) + cachedTracks[(frozenset(artists),title)] = result["image"] + return result + +# with open("apikey","r") as keyfile: +# apikey = keyfile.read().replace("\n","") +# +# +# for a in artists: +# try: +# url = "https://ws.audioscrobbler.com/2.0/?method=track.getinfo&track=" + urllib.parse.quote(title) + "&artist=" + urllib.parse.quote(a) + "&api_key=" + apikey + "&format=json" +# response = urllib.request.urlopen(url) +# lastfm_data = json.loads(response.read()) +# imgurl = lastfm_data["track"]["album"]["image"][2]["#text"] +# break +# except: +# pass +# +# try: +# return {"image":imgurl} +# except: +# for a in artists: +# try: +# return {"image":getArtistInfo(a)["image"]} +# except: +# pass +# +# return {"image":""} + +def getArtistInfo(artist): + import re + import os + + obj = artist + filename = re.sub("[^a-zA-Z0-9]","",artist) + if filename = "": filename = str(hash(obj)) + filepath = "images/artists/" + filename + #filepath_cache = "info/artists_cache/" + filename + + # check if custom image exists + if os.path.exists(filepath + ".png"): + imgurl = "/" + filepath + ".png" + return {"image":imgurl} + elif os.path.exists(filepath + ".jpg"): + imgurl = "/" + filepath + ".jpg" + return {"image":imgurl} + elif os.path.exists(filepath + ".jpeg"): + imgurl = "/" + filepath + ".jpeg" + return {"image":imgurl} #check if cached image exists - elif os.path.exists(filepath_cache + ".png"): - imgurl = "/" + filepath_cache + ".png" - elif os.path.exists(filepath_cache + ".jpg"): - imgurl = "/" + filepath_cache + ".jpg" - elif os.path.exists(filepath_cache + ".jpeg"): - imgurl = "/" + filepath_cache + ".jpeg" +# elif os.path.exists(filepath_cache + ".png"): +# imgurl = "/" + filepath_cache + ".png" +# elif os.path.exists(filepath_cache + ".jpg"): +# imgurl = "/" + filepath_cache + ".jpg" +# elif os.path.exists(filepath_cache + ".jpeg"): +# imgurl = "/" + filepath_cache + ".jpeg" # check if custom desc exists - if os.path.exists(filepath + ".txt"): - with open(filepath + ".txt","r") as descfile: - desc = descfile.read().replace("\n","") - - #check if cached desc exists - elif os.path.exists(filepath_cache + ".txt"): - with open(filepath_cache + ".txt","r") as descfile: - desc = descfile.read().replace("\n","") +# if os.path.exists(filepath + ".txt"): +# with open(filepath + ".txt","r") as descfile: +# desc = descfile.read().replace("\n","") +# +# #check if cached desc exists +# elif os.path.exists(filepath_cache + ".txt"): +# with open(filepath_cache + ".txt","r") as descfile: +# desc = descfile.read().replace("\n","") try: - return {"image":imgurl,"info":desc} - except NameError: - pass - #is this pythonic? - - - # if we neither have a custom image nor a cached version, we return the address from lastfm, but cache that image for later use - with open("apikey","r") as keyfile: - apikey = keyfile.read().replace("\n","") - - - try: - url = "https://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist=" + urllib.parse.quote(artist) + "&api_key=" + apikey + "&format=json" - response = urllib.request.urlopen(url) - lastfm_data = json.loads(response.read()) - try: - imgurl - except NameError: - imgurl = lastfm_data["artist"]["image"][2]["#text"] - if imgurl == "": - imgurl = "/info/artists/default.jpg" - else: - _thread.start_new_thread(cacheImage,(imgurl,"info/artists_cache",filename)) - try: - desc - except NameError: - desc = lastfm_data["artist"]["bio"]["summary"].split("(1) ")[-1] - with open(filepath_cache + ".txt","w") as descfile: - descfile.write(desc) - # this feels so dirty - - - return {"image":imgurl,"info":desc} + return {"image":cachedArtists[artist]} except: - return {"image":"/info/artists/default.jpg","info":"No information available"} + pass + + result = apirequest(artist=artist) + cachedArtists[artist] = result["image"] + return result + +# # if we neither have a custom image nor a cached version, we return the address from lastfm, but cache that image for later use +# with open("apikey","r") as keyfile: +# apikey = keyfile.read().replace("\n","") +# +# +# try: +# url = "https://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist=" + urllib.parse.quote(artist) + "&api_key=" + apikey + "&format=json" +# response = urllib.request.urlopen(url) +# lastfm_data = json.loads(response.read()) +# try: +# imgurl +# except NameError: +# imgurl = lastfm_data["artist"]["image"][2]["#text"] +# if imgurl == "": +# imgurl = "/info/artists/default.jpg" +# else: +# _thread.start_new_thread(cacheImage,(imgurl,"info/artists_cache",filename)) +# try: +# desc +# except NameError: +# desc = lastfm_data["artist"]["bio"]["summary"].split("(1) ")[-1] +# with open(filepath_cache + ".txt","w") as descfile: +# descfile.write(desc) +# # this feels so dirty +# +# +# return {"image":imgurl,"info":desc} +# except: +# return {"image":"/info/artists/default.jpg","info":"No information available"} -def cacheImage(url,path,filename): - import urllib.request - response = urllib.request.urlopen(url) - target = path + "/" + filename + "." + response.info().get_content_subtype() - urllib.request.urlretrieve(url,target) +#def cacheImage(url,path,filename): +# import urllib.request +# response = urllib.request.urlopen(url) +# target = path + "/" + filename + "." + response.info().get_content_subtype() +# urllib.request.urlretrieve(url,target) diff --git a/website/artist.py b/website/artist.py index 4a9c529..995a81e 100644 --- a/website/artist.py +++ b/website/artist.py @@ -9,7 +9,7 @@ def replacedict(keys,dbport): clean(keys) info = getArtistInfo(keys["artist"]) imgurl = info.get("image") - desc = info.get("info") + #desc = info.get("info") response = urllib.request.urlopen("http://localhost:" + str(dbport) + "/artistinfo?artist=" + urllib.parse.quote(keys["artist"])) db_data = json.loads(response.read()) @@ -39,9 +39,9 @@ def replacedict(keys,dbport): html += "" + artistLinks(e["track"]["artists"]) + "" html += "" + trackLink(e["track"]) + "" html += "" + scrobblesTrackLink(e["track"],{},amount=e["scrobbles"]) + "" - html += "" + scrobblesTrackLink(e["track"],{},pixels=e["scrobbles"]*100/maxbar) + "" + html += "" + scrobblesTrackLink(e["track"],{},percent=e["scrobbles"]*100/maxbar) + "" html += "" html += "" - return {"KEY_ARTISTNAME":keys["artist"],"KEY_ENC_ARTISTNAME":urllib.parse.quote(keys["artist"]),"KEY_IMAGEURL":imgurl, "KEY_DESCRIPTION":desc,"KEY_TRACKLIST":html,"KEY_SCROBBLES":scrobbles,"KEY_POSITION":pos,"KEY_ASSOCIATED":includestr} + return {"KEY_ARTISTNAME":keys["artist"],"KEY_ENC_ARTISTNAME":urllib.parse.quote(keys["artist"]),"KEY_IMAGEURL":imgurl, "KEY_DESCRIPTION":"","KEY_TRACKLIST":html,"KEY_SCROBBLES":scrobbles,"KEY_POSITION":pos,"KEY_ASSOCIATED":includestr} diff --git a/website/maloja.css b/website/maloja.css index aefad72..2b63497 100644 --- a/website/maloja.css +++ b/website/maloja.css @@ -79,19 +79,31 @@ table.list tr td { } -table tr:nth-child(even) { +table.list tr:nth-child(even) { background-color:#37373B; } -table tr:nth-child(5n) td { +table.list tr:nth-child(5n) td { border-color:rgba(120,120,120,0.2); } +table.list tr:hover { + background-color:#404044; +} + table td.time { - width:200px; + width:180px; color:gray; } + +table td.icon { + width:20px; + height:20px; + background-size:cover; + background-position:center; +} + table td.artists,td.artist,td.title { width:500px; white-space:nowrap; diff --git a/website/scrobbles.py b/website/scrobbles.py index 4648b03..0da9407 100644 --- a/website/scrobbles.py +++ b/website/scrobbles.py @@ -45,6 +45,7 @@ def replacedict(keys,dbport): for s in scrobbles: html += "" html += "" + getTimeDesc(s["time"]) + "" + #html += """""" html += "" + artistLinks(s["artists"]) + "" html += "" + trackLink({"artists":s["artists"],"title":s["title"]}) + "" html += "" diff --git a/website/track.py b/website/track.py index c08c496..a623eec 100644 --- a/website/track.py +++ b/website/track.py @@ -3,12 +3,12 @@ import json def replacedict(keys,dbport): - from utilities import getArtistInfo + from utilities import getArtistInfo, getTrackInfo from htmlgenerators import clean, artistLink, artistLinks, trackLink, scrobblesTrackLink, keysToUrl, pickKeys, getTimeDesc clean(keys) limitkeys = pickKeys(keys,"artist","title") - info = getArtistInfo(keys["artist"]) + info = getTrackInfo(keys.getall("artist"),keys.get("title")) imgurl = info.get("image") desc = info.get("info")