mirror of
https://github.com/krateng/maloja.git
synced 2025-04-19 10:07:37 +03:00
Significant rework of internal / URI key handling
This commit is contained in:
parent
d46d2be2bf
commit
441be436c6
30
database.py
30
database.py
@ -5,7 +5,7 @@ import waitress
|
||||
from cleanup import *
|
||||
from utilities import *
|
||||
from malojatime import *
|
||||
from htmlgenerators import KeySplit
|
||||
from urihandler import uri_to_internal
|
||||
# doreah toolkit
|
||||
from doreah.logging import log
|
||||
from doreah import tsv
|
||||
@ -196,7 +196,7 @@ def test_server():
|
||||
@dbserver.route("/scrobbles")
|
||||
def get_scrobbles_external():
|
||||
keys = FormsDict.decode(request.query)
|
||||
k_filter, k_time, _, k_amount = KeySplit(keys)
|
||||
k_filter, k_time, _, k_amount = uri_to_internal(keys)
|
||||
ckeys = {**k_filter, **k_time, **k_amount}
|
||||
|
||||
result = get_scrobbles(**ckeys)
|
||||
@ -226,7 +226,7 @@ def get_scrobbles(**keys):
|
||||
@dbserver.route("/numscrobbles")
|
||||
def get_scrobbles_num_external():
|
||||
keys = FormsDict.decode(request.query)
|
||||
k_filter, k_time, _, k_amount = KeySplit(keys)
|
||||
k_filter, k_time, _, k_amount = uri_to_internal(keys)
|
||||
ckeys = {**k_filter, **k_time, **k_amount}
|
||||
|
||||
result = get_scrobbles_num(**ckeys)
|
||||
@ -291,7 +291,7 @@ def get_scrobbles_num(**keys):
|
||||
@dbserver.route("/tracks")
|
||||
def get_tracks_external():
|
||||
keys = FormsDict.decode(request.query)
|
||||
k_filter, _, _, _ = KeySplit(keys,forceArtist=True)
|
||||
k_filter, _, _, _ = uri_to_internal(keys,forceArtist=True)
|
||||
ckeys = {**k_filter}
|
||||
|
||||
result = get_tracks(**ckeys)
|
||||
@ -329,7 +329,7 @@ def get_artists():
|
||||
@dbserver.route("/charts/artists")
|
||||
def get_charts_artists_external():
|
||||
keys = FormsDict.decode(request.query)
|
||||
_, k_time, _, _ = KeySplit(keys)
|
||||
_, k_time, _, _ = uri_to_internal(keys)
|
||||
ckeys = {**k_time}
|
||||
|
||||
result = get_charts_artists(**ckeys)
|
||||
@ -346,7 +346,7 @@ def get_charts_artists(**keys):
|
||||
@dbserver.route("/charts/tracks")
|
||||
def get_charts_tracks_external():
|
||||
keys = FormsDict.decode(request.query)
|
||||
k_filter, k_time, _, _ = KeySplit(keys,forceArtist=True)
|
||||
k_filter, k_time, _, _ = uri_to_internal(keys,forceArtist=True)
|
||||
ckeys = {**k_filter, **k_time}
|
||||
|
||||
result = get_charts_tracks(**ckeys)
|
||||
@ -366,7 +366,7 @@ def get_charts_tracks(**keys):
|
||||
@dbserver.route("/pulse")
|
||||
def get_pulse_external():
|
||||
keys = FormsDict.decode(request.query)
|
||||
k_filter, k_time, k_internal, k_amount = KeySplit(keys)
|
||||
k_filter, k_time, k_internal, k_amount = uri_to_internal(keys)
|
||||
ckeys = {**k_filter, **k_time, **k_internal, **k_amount}
|
||||
|
||||
results = get_pulse(**ckeys)
|
||||
@ -394,7 +394,7 @@ def get_pulse(**keys):
|
||||
def get_top_artists_external():
|
||||
|
||||
keys = FormsDict.decode(request.query)
|
||||
_, k_time, k_internal, _ = KeySplit(keys)
|
||||
_, k_time, k_internal, _ = uri_to_internal(keys)
|
||||
ckeys = {**k_time, **k_internal}
|
||||
|
||||
results = get_top_artists(**ckeys)
|
||||
@ -408,9 +408,9 @@ def get_top_artists(**keys):
|
||||
for (a,b) in rngs:
|
||||
try:
|
||||
res = db_aggregate(since=a,to=b,by="ARTIST")[0]
|
||||
results.append({"from":a,"to":b,"artist":res["artist"],"counting":res["counting"],"scrobbles":res["scrobbles"]})
|
||||
results.append({"since":a,"to":b,"artist":res["artist"],"counting":res["counting"],"scrobbles":res["scrobbles"]})
|
||||
except:
|
||||
results.append({"from":a,"to":b,"artist":None,"scrobbles":0})
|
||||
results.append({"since":a,"to":b,"artist":None,"scrobbles":0})
|
||||
|
||||
return results
|
||||
|
||||
@ -426,7 +426,7 @@ def get_top_artists(**keys):
|
||||
@dbserver.route("/top/tracks")
|
||||
def get_top_tracks_external():
|
||||
keys = FormsDict.decode(request.query)
|
||||
_, k_time, k_internal, _ = KeySplit(keys)
|
||||
_, k_time, k_internal, _ = uri_to_internal(keys)
|
||||
ckeys = {**k_time, **k_internal}
|
||||
|
||||
# IMPLEMENT THIS FOR TOP TRACKS OF ARTIST AS WELL?
|
||||
@ -442,9 +442,9 @@ def get_top_tracks(**keys):
|
||||
for (a,b) in rngs:
|
||||
try:
|
||||
res = db_aggregate(since=a,to=b,by="TRACK")[0]
|
||||
results.append({"from":a,"to":b,"track":res["track"],"scrobbles":res["scrobbles"]})
|
||||
results.append({"since":a,"to":b,"track":res["track"],"scrobbles":res["scrobbles"]})
|
||||
except:
|
||||
results.append({"from":a,"to":b,"track":None,"scrobbles":0})
|
||||
results.append({"since":a,"to":b,"track":None,"scrobbles":0})
|
||||
|
||||
return results
|
||||
|
||||
@ -461,7 +461,7 @@ def get_top_tracks(**keys):
|
||||
@dbserver.route("/artistinfo")
|
||||
def artistInfo_external():
|
||||
keys = FormsDict.decode(request.query)
|
||||
k_filter, _, _, _ = KeySplit(keys,forceArtist=True)
|
||||
k_filter, _, _, _ = uri_to_internal(keys,forceArtist=True)
|
||||
ckeys = {**k_filter}
|
||||
|
||||
results = artistInfo(**ckeys)
|
||||
@ -490,7 +490,7 @@ def artistInfo(artist):
|
||||
@dbserver.route("/trackinfo")
|
||||
def trackInfo_external():
|
||||
keys = FormsDict.decode(request.query)
|
||||
k_filter, _, _, _ = KeySplit(keys,forceTrack=True)
|
||||
k_filter, _, _, _ = uri_to_internal(keys,forceTrack=True)
|
||||
ckeys = {**k_filter}
|
||||
|
||||
results = trackInfo(**ckeys)
|
||||
|
@ -1,7 +1,7 @@
|
||||
import urllib
|
||||
from bottle import FormsDict
|
||||
import datetime
|
||||
from malojatime import uri_to_internal, internal_to_uri
|
||||
from urihandler import compose_querystring
|
||||
|
||||
|
||||
# returns the proper column(s) for an artist or track
|
||||
@ -40,175 +40,19 @@ def trackLink(track):
|
||||
def scrobblesTrackLink(track,timekeys,amount=None,percent=None):
|
||||
artists,title = track["artists"],track["title"]
|
||||
inner = str(amount) if amount is not None else "<div style='width:" + str(percent) + "%;'></div>"
|
||||
return "<a href='/scrobbles?" + "&".join(["artist=" + urllib.parse.quote(a) for a in artists]) + "&title=" + urllib.parse.quote(title) + "&" + keysToUrl(timekeys) + "'>" + inner + "</a>"
|
||||
return "<a href='/scrobbles?" + "&".join(["artist=" + urllib.parse.quote(a) for a in artists]) + "&title=" + urllib.parse.quote(title) + "&" + compose_querystring(timekeys) + "'>" + inner + "</a>"
|
||||
|
||||
def scrobblesArtistLink(artist,timekeys,amount=None,percent=None,associated=False):
|
||||
inner = str(amount) if amount is not None else "<div style='width:" + str(percent) + "%;'></div>"
|
||||
askey = "&associated" if associated else ""
|
||||
return "<a href='/scrobbles?artist=" + urllib.parse.quote(artist) + "&" + keysToUrl(timekeys) + askey + "'>" + inner + "</a>"
|
||||
return "<a href='/scrobbles?artist=" + urllib.parse.quote(artist) + "&" + compose_querystring(timekeys) + askey + "'>" + inner + "</a>"
|
||||
|
||||
def scrobblesLink(timekeys,amount=None,percent=None,artist=None,track=None,associated=False):
|
||||
if track is not None: return scrobblesTrackLink(track,timekeys,amount,percent)
|
||||
if artist is not None: return scrobblesArtistLink(artist,timekeys,amount,percent,associated)
|
||||
inner = str(amount) if amount is not None else "<div style='width:" + str(percent) + "%;'></div>"
|
||||
return "<a href='/scrobbles?" + keysToUrl(timekeys) + "'>" + inner + "</a>"
|
||||
return "<a href='/scrobbles?" + compose_querystring(timekeys) + "'>" + inner + "</a>"
|
||||
|
||||
# necessary because urllib.parse.urlencode doesnt handle multidicts
|
||||
def keysToUrl(*dicts,exclude=[]):
|
||||
for dict in dicts:
|
||||
for key in dict:
|
||||
dict[key] = internal_to_uri(dict[key])
|
||||
st = ""
|
||||
keys = removeIdentical(*dicts)
|
||||
for k in keys:
|
||||
if k in exclude: continue
|
||||
values = keys.getall(k)
|
||||
st += "&".join([urllib.parse.urlencode({k:v},safe="/") for v in values])
|
||||
st += "&"
|
||||
return st
|
||||
|
||||
|
||||
def removeIdentical(*dicts):
|
||||
#combine multiple dicts
|
||||
keys = FormsDict()
|
||||
for d in dicts:
|
||||
for k in d:
|
||||
try: #multidicts
|
||||
for v in d.getall(k):
|
||||
keys.append(k,v)
|
||||
except: #normaldicts
|
||||
v = d.get(k)
|
||||
keys.append(k,v)
|
||||
|
||||
new = FormsDict()
|
||||
for k in keys:
|
||||
values = set(keys.getall(k))
|
||||
for v in values:
|
||||
new.append(k,v)
|
||||
|
||||
return new
|
||||
|
||||
#def getTimeDesc(timestamp,short=False):
|
||||
# tim = datetime.datetime.utcfromtimestamp(timestamp)
|
||||
# if short:
|
||||
# now = datetime.datetime.now(tz=datetime.timezone.utc)
|
||||
# difference = int(now.timestamp() - timestamp)
|
||||
#
|
||||
# if difference < 10: return "just now"
|
||||
# if difference < 60: return str(difference) + " seconds ago"
|
||||
# difference = int(difference/60)
|
||||
# if difference < 60: return str(difference) + " minutes ago" if difference>1 else str(difference) + " minute ago"
|
||||
# difference = int(difference/60)
|
||||
# if difference < 24: return str(difference) + " hours ago" if difference>1 else str(difference) + " hour ago"
|
||||
# difference = int(difference/24)
|
||||
# if difference < 5: return tim.strftime("%A")
|
||||
# if difference < 31: return str(difference) + " days ago" if difference>1 else str(difference) + " day ago"
|
||||
# #if difference < 300 and tim.year == now.year: return tim.strftime("%B")
|
||||
# #if difference < 300: return tim.strftime("%B %Y")
|
||||
#
|
||||
# return tim.strftime("%d. %B %Y")
|
||||
# else:
|
||||
# return tim.strftime("%d. %b %Y %I:%M %p")
|
||||
|
||||
#def getRangeDesc(since=None,to=None,inclusiveB=True):
|
||||
# # string to list
|
||||
# if isinstance(timeA,str): timeA = timeA.split("/")
|
||||
# if isinstance(timeB,str): timeB = timeB.split("/")
|
||||
#
|
||||
# # if lists, we have it potentially much easier:
|
||||
# if isinstance(timeA,list) and isinstance(timeB,list):
|
||||
# if timeA == timeB:
|
||||
# date = [1970,1,1]
|
||||
# date[:len(timeA)] = timeA
|
||||
# dto = datetime.datetime(date[0],date[1],date[2],tzinfo=datetime.timezone.utc)
|
||||
# if len(timeA) == 3:
|
||||
# return dto.strftime("%d. %b %Y")
|
||||
# if len(timeA) == 2:
|
||||
# return dto.strftime("%B %Y")
|
||||
# if len(timeA) == 1:
|
||||
# return dto.strftime("%Y")
|
||||
#
|
||||
#
|
||||
#
|
||||
# (timeA, timeB) = getTimestamps(since=timeA, to=timeB)
|
||||
#
|
||||
#
|
||||
# return getTimeDesc(timeA) + " to " + getTimeDesc(timeB)
|
||||
|
||||
|
||||
|
||||
# finds out if we want an artist or a track
|
||||
#def interpretURLKeys(keys):
|
||||
# if "title" in keys:
|
||||
# return {"track":{"artists":keys.getall("artist"),"title":keys.get("title")}}
|
||||
# if "artist" in keys:
|
||||
# return {"artist":keys.get("artist")}
|
||||
#
|
||||
# return {}
|
||||
|
||||
# alright this is the last one
|
||||
# one ultimate method to rule them all
|
||||
# one method to take html keys and convert them into internal keys
|
||||
# it renames them, interprets what's being asked, removes duplicates
|
||||
# it gets rid of multidicts
|
||||
# it does fecking everything
|
||||
# it's the best
|
||||
# fantastic
|
||||
def KeySplit(keys,forceTrack=False,forceArtist=False):
|
||||
|
||||
# output:
|
||||
# 1 keys that define the filtered object like artist or track
|
||||
# 2 keys that define time limits of the whole thing
|
||||
# 3 keys that define interal time ranges
|
||||
# 4 keys that define amount limits
|
||||
|
||||
# 1
|
||||
if "title" in keys and not forceArtist:
|
||||
resultkeys1 = {"track":{"artists":keys.getall("artist"),"title":keys.get("title")}}
|
||||
elif "artist" in keys and not forceTrack:
|
||||
resultkeys1 = {"artist":keys.get("artist")}
|
||||
if "associated" in keys: resultkeys1["associated"] = True
|
||||
else:
|
||||
resultkeys1 = {}
|
||||
|
||||
# 2
|
||||
resultkeys2 = {}
|
||||
if "since" in keys: resultkeys2["since"] = keys.get("since")
|
||||
elif "from" in keys: resultkeys2["since"] = keys.get("from")
|
||||
elif "start" in keys: resultkeys2["since"] = keys.get("start")
|
||||
#
|
||||
if "to" in keys: resultkeys2["to"] = keys.get("to")
|
||||
elif "until" in keys: resultkeys2["to"] = keys.get("until")
|
||||
elif "end" in keys: resultkeys2["to"] = keys.get("end")
|
||||
#
|
||||
if "since" in resultkeys2 and "to" in resultkeys2 and resultkeys2["since"] == resultkeys2["to"]:
|
||||
resultkeys2["within"] = resultkeys2["since"]
|
||||
del resultkeys2["since"]
|
||||
del resultkeys2["to"]
|
||||
#
|
||||
if "in" in keys: resultkeys2["within"] = keys.get("in")
|
||||
elif "within" in keys: resultkeys2["within"] = keys.get("within")
|
||||
elif "during" in keys: resultkeys2["within"] = keys.get("during")
|
||||
if "within" in resultkeys2:
|
||||
if "since" in resultkeys2:
|
||||
del resultkeys2["since"]
|
||||
if "to" in resultkeys2:
|
||||
del resultkeys2["to"]
|
||||
|
||||
|
||||
#3
|
||||
resultkeys3 = {}
|
||||
if "step" in keys: [resultkeys3["step"],resultkeys3["stepn"]] = (keys["step"].split("-") + [1])[:2]
|
||||
if "stepn" in keys: resultkeys3["stepn"] = keys["stepn"] #overwrite if explicitly given
|
||||
if "stepn" in resultkeys3: resultkeys3["stepn"] = int(resultkeys3["stepn"]) #in both cases, convert it here
|
||||
if "trail" in keys: resultkeys3["trail"] = int(keys["trail"])
|
||||
|
||||
|
||||
#4
|
||||
resultkeys4 = {}
|
||||
if "max" in keys: resultkeys4["max_"] = int(keys["max"])
|
||||
|
||||
return resultkeys1, resultkeys2, resultkeys3, resultkeys4
|
||||
|
||||
|
||||
# limit a multidict to only the specified keys
|
||||
@ -226,12 +70,3 @@ def pickKeys(d,*keys):
|
||||
finald.append(k,v)
|
||||
|
||||
return finald
|
||||
|
||||
# removes all duplicate keys, except artists when a title is specified
|
||||
#def clean(d):
|
||||
# if isinstance(d,dict):
|
||||
# return
|
||||
# else:
|
||||
# for k in d:
|
||||
# if (k != "artist") or "title" not in d:
|
||||
# d[k] = d.pop(k)
|
||||
|
@ -2,6 +2,7 @@ from htmlgenerators import *
|
||||
import database
|
||||
from utilities import getArtistImage, getTrackImage
|
||||
from malojatime import *
|
||||
from urihandler import compose_querystring, internal_to_uri
|
||||
import urllib
|
||||
|
||||
|
||||
@ -144,8 +145,8 @@ def module_trackcharts(max_=None,**kwargs):
|
||||
# track
|
||||
html += entity_column(e["track"])
|
||||
# scrobbles
|
||||
html += "<td class='amount'>" + scrobblesTrackLink(e["track"],kwargs_time,amount=e["scrobbles"]) + "</td>"
|
||||
html += "<td class='bar'>" + scrobblesTrackLink(e["track"],kwargs_time,percent=e["scrobbles"]*100/maxbar) + "</td>"
|
||||
html += "<td class='amount'>" + scrobblesTrackLink(e["track"],internal_to_uri(kwargs_time),amount=e["scrobbles"]) + "</td>"
|
||||
html += "<td class='bar'>" + scrobblesTrackLink(e["track"],internal_to_uri(kwargs_time),percent=e["scrobbles"]*100/maxbar) + "</td>"
|
||||
html += "</tr>"
|
||||
prev = e
|
||||
html += "</table>"
|
||||
@ -205,8 +206,8 @@ def module_artistcharts(max_=None,**kwargs):
|
||||
# artist
|
||||
html += entity_column(e["artist"],counting=e["counting"])
|
||||
# scrobbles
|
||||
html += "<td class='amount'>" + scrobblesArtistLink(e["artist"],kwargs_time,amount=e["scrobbles"],associated=True) + "</td>"
|
||||
html += "<td class='bar'>" + scrobblesArtistLink(e["artist"],kwargs_time,percent=e["scrobbles"]*100/maxbar,associated=True) + "</td>"
|
||||
html += "<td class='amount'>" + scrobblesArtistLink(e["artist"],internal_to_uri(kwargs_time),amount=e["scrobbles"],associated=True) + "</td>"
|
||||
html += "<td class='bar'>" + scrobblesArtistLink(e["artist"],internal_to_uri(kwargs_time),percent=e["scrobbles"]*100/maxbar,associated=True) + "</td>"
|
||||
html += "</tr>"
|
||||
prev = e
|
||||
|
||||
@ -245,14 +246,15 @@ def module_toptracks(pictures=True,**kwargs):
|
||||
html = "<table class='list'>"
|
||||
for e in tracks:
|
||||
|
||||
fromstr = "/".join([str(p) for p in e["from"]])
|
||||
tostr = "/".join([str(p) for p in e["to"]])
|
||||
#fromstr = "/".join([str(p) for p in e["from"]])
|
||||
#tostr = "/".join([str(p) for p in e["to"]])
|
||||
limits = pickKeys(e,"since","to")
|
||||
|
||||
i += 1
|
||||
html += "<tr>"
|
||||
|
||||
|
||||
html += "<td>" + range_desc(e["from"],e["to"],short=True) + "</td>"
|
||||
html += "<td>" + range_desc(e["since"],e["to"],short=True) + "</td>"
|
||||
if e["track"] is None:
|
||||
if pictures:
|
||||
html += "<td><div></div></td>"
|
||||
@ -265,8 +267,8 @@ def module_toptracks(pictures=True,**kwargs):
|
||||
img = getTrackImage(e["track"]["artists"],e["track"]["title"],fast=True)
|
||||
else: img = None
|
||||
html += entity_column(e["track"],image=img)
|
||||
html += "<td class='amount'>" + scrobblesTrackLink(e["track"],{"since":fromstr,"to":tostr},amount=e["scrobbles"]) + "</td>"
|
||||
html += "<td class='bar'>" + scrobblesTrackLink(e["track"],{"since":fromstr,"to":tostr},percent=e["scrobbles"]*100/maxbar) + "</td>"
|
||||
html += "<td class='amount'>" + scrobblesTrackLink(e["track"],internal_to_uri(limits),amount=e["scrobbles"]) + "</td>"
|
||||
html += "<td class='bar'>" + scrobblesTrackLink(e["track"],internal_to_uri(limits),percent=e["scrobbles"]*100/maxbar) + "</td>"
|
||||
html += "</tr>"
|
||||
prev = e
|
||||
html += "</table>"
|
||||
@ -300,14 +302,15 @@ def module_topartists(pictures=True,**kwargs):
|
||||
html = "<table class='list'>"
|
||||
for e in artists:
|
||||
|
||||
fromstr = "/".join([str(p) for p in e["from"]])
|
||||
tostr = "/".join([str(p) for p in e["to"]])
|
||||
#fromstr = "/".join([str(p) for p in e["from"]])
|
||||
#tostr = "/".join([str(p) for p in e["to"]])
|
||||
limits = pickKeys(e,"since","to")
|
||||
|
||||
i += 1
|
||||
html += "<tr>"
|
||||
|
||||
|
||||
html += "<td>" + range_desc(e["from"],e["to"],short=True) + "</td>"
|
||||
html += "<td>" + range_desc(e["since"],e["to"],short=True) + "</td>"
|
||||
|
||||
if e["artist"] is None:
|
||||
if pictures:
|
||||
@ -320,8 +323,8 @@ def module_topartists(pictures=True,**kwargs):
|
||||
img = getArtistImage(e["artist"],fast=True)
|
||||
else: img = None
|
||||
html += entity_column(e["artist"],image=img)
|
||||
html += "<td class='amount'>" + scrobblesArtistLink(e["artist"],{"since":fromstr,"to":tostr},amount=e["scrobbles"],associated=True) + "</td>"
|
||||
html += "<td class='bar'>" + scrobblesArtistLink(e["artist"],{"since":fromstr,"to":tostr},percent=e["scrobbles"]*100/maxbar,associated=True) + "</td>"
|
||||
html += "<td class='amount'>" + scrobblesArtistLink(e["artist"],internal_to_uri(limits),amount=e["scrobbles"],associated=True) + "</td>"
|
||||
html += "<td class='bar'>" + scrobblesArtistLink(e["artist"],internal_to_uri(limits),percent=e["scrobbles"]*100/maxbar,associated=True) + "</td>"
|
||||
html += "</tr>"
|
||||
prev = e
|
||||
html += "</table>"
|
||||
@ -439,17 +442,14 @@ def module_trackcharts_tiles(**kwargs):
|
||||
return html
|
||||
|
||||
|
||||
|
||||
# THIS FUNCTION USES THE ORIGINAL URI KEYS!!!
|
||||
def module_filterselection(keys,time=True,delimit=False):
|
||||
# all other keys that will not be changed by clicking another filter
|
||||
|
||||
|
||||
html = ""
|
||||
|
||||
|
||||
if time:
|
||||
|
||||
keystr = "?" + keysToUrl(keys,exclude=["since","to","in"])
|
||||
# all other keys that will not be changed by clicking another filter
|
||||
keystr = "?" + compose_querystring(keys,exclude=["since","to","in"])
|
||||
|
||||
|
||||
# wonky selector for precise date range
|
||||
@ -506,7 +506,7 @@ def module_filterselection(keys,time=True,delimit=False):
|
||||
|
||||
if delimit:
|
||||
|
||||
keystr = "?" + keysToUrl(keys,exclude=["step","stepn"])
|
||||
keystr = "?" + compose_querystring(keys,exclude=["step","stepn"])
|
||||
|
||||
html += "<div>"
|
||||
if keys.get("step") == "day":
|
||||
@ -530,7 +530,7 @@ def module_filterselection(keys,time=True,delimit=False):
|
||||
|
||||
|
||||
|
||||
keystr = "?" + keysToUrl(keys,exclude=["trail"])
|
||||
keystr = "?" + compose_querystring(keys,exclude=["trail"])
|
||||
|
||||
html += "<div>"
|
||||
if keys.get("trail") == "1" or keys.get("trail") is None:
|
||||
|
2
maloja
2
maloja
@ -280,6 +280,8 @@ def update():
|
||||
|
||||
os.chmod("./maloja",os.stat("./maloja").st_mode | stat.S_IXUSR)
|
||||
|
||||
print("Make sure to install the latest version of doreah! (" + yellow("pip3 install --upgrade --no-cache-dir doreah") + ")")
|
||||
|
||||
if stop(): start() #stop returns whether it was running before, in which case we restart it
|
||||
|
||||
|
||||
|
@ -22,15 +22,18 @@ def end_of_scrobbling():
|
||||
|
||||
|
||||
|
||||
def uri_to_internal(t):
|
||||
return time_fix(t)
|
||||
#def uri_to_internal(t):
|
||||
# return time_fix(t)
|
||||
#
|
||||
#def internal_to_uri(t):
|
||||
# if isinstance(t,list) or isinstance(t,tuple):
|
||||
# return "/".join(str(t))
|
||||
#
|
||||
# return str(t)
|
||||
|
||||
def internal_to_uri(t):
|
||||
if isinstance(t,list) or isinstance(t,tuple):
|
||||
return "/".join(str(t))
|
||||
|
||||
return str(t)
|
||||
|
||||
def time_str(t):
|
||||
return "/".join(str(tp) for tp in t)
|
||||
|
||||
# converts strings and stuff to lists
|
||||
def time_fix(t):
|
||||
|
@ -75,7 +75,7 @@ replaceartist Ace of Angels AOA
|
||||
replacetitle 사뿐사뿐 (Like a Cat) Like a Cat
|
||||
replacetitle Like A Cat (Japanese Version) Like a Cat (Japanese Version)
|
||||
replacetitle MOYA (inst) Moya
|
||||
replacetitle MOYA (instrumental) Moya
|
||||
replacetitle MOYA (instrumental) Moya (instrumental)
|
||||
countas AOA Black AOA
|
||||
|
||||
# Girl's Day
|
||||
|
Can't render this file because it has a wrong number of fields in line 5.
|
BIN
scrobblers/maloja-scrobbler.zip
Normal file
BIN
scrobblers/maloja-scrobbler.zip
Normal file
Binary file not shown.
@ -5,9 +5,8 @@ from bottle import Bottle, route, get, post, error, run, template, static_file,
|
||||
import waitress
|
||||
# rest of the project
|
||||
import database
|
||||
from htmlgenerators import removeIdentical
|
||||
from utilities import *
|
||||
from htmlgenerators import KeySplit
|
||||
from urihandler import uri_to_internal, remove_identical
|
||||
# doreah toolkit
|
||||
from doreah import settings
|
||||
from doreah.logging import log
|
||||
@ -113,7 +112,7 @@ def graceful_exit(sig=None,frame=None):
|
||||
@webserver.route("/image")
|
||||
def dynamic_image():
|
||||
keys = FormsDict.decode(request.query)
|
||||
relevant, _, _, _ = KeySplit(keys)
|
||||
relevant, _, _, _ = uri_to_internal(keys)
|
||||
result = resolveImage(**relevant)
|
||||
if result == "": return ""
|
||||
redirect(result,307)
|
||||
@ -162,7 +161,7 @@ def static(name):
|
||||
@webserver.route("/<name>")
|
||||
def static_html(name):
|
||||
linkheaders = ["</css/maloja.css>; rel=preload; as=style"]
|
||||
keys = removeIdentical(FormsDict.decode(request.query))
|
||||
keys = remove_identical(FormsDict.decode(request.query))
|
||||
|
||||
with open("website/" + name + ".html") as htmlfile:
|
||||
html = htmlfile.read()
|
||||
|
133
urihandler.py
Normal file
133
urihandler.py
Normal file
@ -0,0 +1,133 @@
|
||||
import urllib
|
||||
from bottle import FormsDict
|
||||
from malojatime import time_fix, time_str
|
||||
|
||||
|
||||
# necessary because urllib.parse.urlencode doesnt handle multidicts
|
||||
def compose_querystring(*dicts,exclude=[]):
|
||||
|
||||
st = ""
|
||||
keys = remove_identical(*dicts)
|
||||
for k in keys:
|
||||
if k in exclude: continue
|
||||
values = keys.getall(k)
|
||||
st += "&".join([urllib.parse.urlencode({k:v},safe="/") for v in values])
|
||||
st += "&"
|
||||
return st
|
||||
|
||||
|
||||
# takes any number of multidicts and normal dicts and creates a formsdict with duplicate values removed
|
||||
def remove_identical(*dicts):
|
||||
#combine multiple dicts
|
||||
keys = FormsDict()
|
||||
for d in dicts:
|
||||
for k in d:
|
||||
try: #multidicts
|
||||
for v in d.getall(k):
|
||||
keys.append(k,v)
|
||||
except: #normaldicts
|
||||
v = d.get(k)
|
||||
keys.append(k,v)
|
||||
|
||||
new = FormsDict()
|
||||
for k in keys:
|
||||
#values = set(keys.getall(k))
|
||||
values = keys.getall(k) # NO IDENTICAL REMOVAL FOR NOW
|
||||
for v in values:
|
||||
new.append(k,v)
|
||||
|
||||
return new
|
||||
|
||||
|
||||
|
||||
def uri_to_internal(keys,forceTrack=False,forceArtist=False):
|
||||
|
||||
# output:
|
||||
# 1 keys that define the filtered object like artist or track
|
||||
# 2 keys that define time limits of the whole thing
|
||||
# 3 keys that define interal time ranges
|
||||
# 4 keys that define amount limits
|
||||
|
||||
# 1
|
||||
if "title" in keys and not forceArtist:
|
||||
resultkeys1 = {"track":{"artists":keys.getall("artist"),"title":keys.get("title")}}
|
||||
elif "artist" in keys and not forceTrack:
|
||||
resultkeys1 = {"artist":keys.get("artist")}
|
||||
if "associated" in keys: resultkeys1["associated"] = True
|
||||
else:
|
||||
resultkeys1 = {}
|
||||
|
||||
# 2
|
||||
resultkeys2 = {}
|
||||
if "since" in keys: resultkeys2["since"] = time_fix(keys.get("since"))
|
||||
elif "from" in keys: resultkeys2["since"] = time_fix(keys.get("from"))
|
||||
elif "start" in keys: resultkeys2["since"] = time_fix(keys.get("start"))
|
||||
#
|
||||
if "to" in keys: resultkeys2["to"] = time_fix(keys.get("to"))
|
||||
elif "until" in keys: resultkeys2["to"] = time_fix(keys.get("until"))
|
||||
elif "end" in keys: resultkeys2["to"] = time_fix(keys.get("end"))
|
||||
#
|
||||
if "since" in resultkeys2 and "to" in resultkeys2 and resultkeys2["since"] == resultkeys2["to"]:
|
||||
resultkeys2["within"] = resultkeys2["since"]
|
||||
del resultkeys2["since"]
|
||||
del resultkeys2["to"]
|
||||
#
|
||||
if "in" in keys: resultkeys2["within"] = time_fix(keys.get("in"))
|
||||
elif "within" in keys: resultkeys2["within"] = time_fix(keys.get("within"))
|
||||
elif "during" in keys: resultkeys2["within"] = time_fix(keys.get("during"))
|
||||
if "within" in resultkeys2:
|
||||
if "since" in resultkeys2:
|
||||
del resultkeys2["since"]
|
||||
if "to" in resultkeys2:
|
||||
del resultkeys2["to"]
|
||||
|
||||
|
||||
#3
|
||||
resultkeys3 = {}
|
||||
if "step" in keys: [resultkeys3["step"],resultkeys3["stepn"]] = (keys["step"].split("-") + [1])[:2]
|
||||
if "stepn" in keys: resultkeys3["stepn"] = keys["stepn"] #overwrite if explicitly given
|
||||
if "stepn" in resultkeys3: resultkeys3["stepn"] = int(resultkeys3["stepn"]) #in both cases, convert it here
|
||||
if "trail" in keys: resultkeys3["trail"] = int(keys["trail"])
|
||||
|
||||
|
||||
#4
|
||||
resultkeys4 = {}
|
||||
if "max" in keys: resultkeys4["max_"] = int(keys["max"])
|
||||
|
||||
return resultkeys1, resultkeys2, resultkeys3, resultkeys4
|
||||
|
||||
def internal_to_uri(keys):
|
||||
urikeys = FormsDict()
|
||||
|
||||
#filter
|
||||
if "artist" in keys:
|
||||
urikeys.append("artist",keys["artist"])
|
||||
if keys.get("associated"): urikeys.append("associated","yes")
|
||||
elif "track" in keys:
|
||||
for a in keys["track"]["artists"]:
|
||||
urikeys.append("artist",a)
|
||||
urikeys.append("title",keys["track"]["title"])
|
||||
|
||||
#time
|
||||
if "within" in keys:
|
||||
urikeys.append("in",time_str(keys["within"]))
|
||||
else:
|
||||
if "since" in keys:
|
||||
urikeys.append("since",time_str(keys["since"]))
|
||||
if "to" in keys:
|
||||
urikeys.append("to",time_str(keys["to"]))
|
||||
|
||||
# delimit
|
||||
if "step" in keys:
|
||||
urikeys.append("step",keys["step"])
|
||||
if "stepn" in keys:
|
||||
urikeys.append("stepn",str(keys["stepn"]))
|
||||
if "trail" in keys:
|
||||
urikeys.append("trail",str(keys["trail"]))
|
||||
|
||||
# stuff
|
||||
if "max_" in keys:
|
||||
urikeys.append("max",str(keys["max_"]))
|
||||
|
||||
|
||||
return urikeys
|
@ -4,10 +4,11 @@ import database
|
||||
|
||||
def instructions(keys):
|
||||
from utilities import getArtistImage
|
||||
from htmlgenerators import artistLink, artistLinks, KeySplit
|
||||
from htmlgenerators import artistLink, artistLinks
|
||||
from urihandler import compose_querystring, uri_to_internal
|
||||
from htmlmodules import module_pulse, module_trackcharts
|
||||
|
||||
filterkeys, _, _, _ = KeySplit(keys,forceArtist=True)
|
||||
filterkeys, _, _, _ = uri_to_internal(keys,forceArtist=True)
|
||||
imgurl = getArtistImage(filterkeys["artist"],fast=True)
|
||||
pushresources = [{"file":imgurl,"type":"image"}] if imgurl.startswith("/") else []
|
||||
|
||||
|
@ -3,12 +3,12 @@ import urllib
|
||||
|
||||
def instructions(keys):
|
||||
from utilities import getArtistImage
|
||||
from htmlgenerators import KeySplit
|
||||
from urihandler import compose_querystring, uri_to_internal
|
||||
from htmlmodules import module_artistcharts, module_filterselection
|
||||
from malojatime import range_desc
|
||||
|
||||
|
||||
_, timekeys, _, amountkeys = KeySplit(keys)
|
||||
_, timekeys, _, amountkeys = uri_to_internal(keys)
|
||||
|
||||
limitstring = range_desc(**timekeys)
|
||||
|
||||
|
@ -3,11 +3,12 @@ import urllib
|
||||
|
||||
def instructions(keys):
|
||||
from utilities import getArtistImage, getTrackImage
|
||||
from htmlgenerators import artistLink, KeySplit
|
||||
from htmlgenerators import artistLink
|
||||
from urihandler import compose_querystring, uri_to_internal
|
||||
from htmlmodules import module_trackcharts, module_filterselection
|
||||
from malojatime import range_desc
|
||||
|
||||
filterkeys, timekeys, _, amountkeys = KeySplit(keys)
|
||||
filterkeys, timekeys, _, amountkeys = uri_to_internal(keys)
|
||||
|
||||
|
||||
limitstring = ""
|
||||
|
@ -4,11 +4,12 @@ import database
|
||||
|
||||
def instructions(keys):
|
||||
from utilities import getArtistImage, getTrackImage
|
||||
from htmlgenerators import artistLink, artistLinks, trackLink, scrobblesLink, keysToUrl, KeySplit
|
||||
from htmlgenerators import artistLink, artistLinks, trackLink, scrobblesLink
|
||||
from urihandler import compose_querystring, uri_to_internal
|
||||
from htmlmodules import module_pulse, module_filterselection
|
||||
from malojatime import range_desc, delimit_desc
|
||||
|
||||
filterkeys, timekeys, delimitkeys, _ = KeySplit(keys)
|
||||
filterkeys, timekeys, delimitkeys, _ = uri_to_internal(keys)
|
||||
|
||||
|
||||
# describe the scope (and creating a key for the relevant artist or track)
|
||||
|
@ -4,12 +4,13 @@ import database
|
||||
|
||||
def instructions(keys):
|
||||
from utilities import getArtistImage, getTrackImage
|
||||
from htmlgenerators import artistLink, artistLinks, trackLink, KeySplit
|
||||
from htmlgenerators import artistLink, artistLinks, trackLink
|
||||
from urihandler import compose_querystring, uri_to_internal
|
||||
from htmlmodules import module_scrobblelist, module_filterselection
|
||||
from malojatime import range_desc
|
||||
|
||||
|
||||
filterkeys, timekeys, _, amountkeys = KeySplit(keys)
|
||||
filterkeys, timekeys, _, amountkeys = uri_to_internal(keys)
|
||||
|
||||
# describe the scope
|
||||
limitstring = ""
|
||||
|
@ -3,11 +3,12 @@ import urllib
|
||||
|
||||
def instructions(keys):
|
||||
from utilities import getArtistImage, getTrackImage
|
||||
from htmlgenerators import artistLink, KeySplit
|
||||
from htmlgenerators import artistLink
|
||||
from urihandler import compose_querystring, uri_to_internal
|
||||
from htmlmodules import module_topartists, module_filterselection
|
||||
from malojatime import range_desc
|
||||
|
||||
_, timekeys, delimitkeys, _ = KeySplit(keys)
|
||||
_, timekeys, delimitkeys, _ = uri_to_internal(keys)
|
||||
|
||||
|
||||
limitstring = ""
|
||||
|
@ -3,11 +3,12 @@ import urllib
|
||||
|
||||
def instructions(keys):
|
||||
from utilities import getArtistImage, getTrackImage
|
||||
from htmlgenerators import artistLink, KeySplit
|
||||
from htmlgenerators import artistLink
|
||||
from urihandler import compose_querystring, uri_to_internal
|
||||
from htmlmodules import module_toptracks, module_filterselection
|
||||
from malojatime import range_desc
|
||||
|
||||
filterkeys, timekeys, delimitkeys, _ = KeySplit(keys)
|
||||
filterkeys, timekeys, delimitkeys, _ = uri_to_internal(keys)
|
||||
|
||||
|
||||
limitstring = ""
|
||||
|
@ -4,11 +4,12 @@ import database
|
||||
|
||||
def instructions(keys):
|
||||
from utilities import getArtistImage, getTrackImage
|
||||
from htmlgenerators import artistLinks, keysToUrl, KeySplit
|
||||
from htmlgenerators import artistLinks
|
||||
from urihandler import compose_querystring
|
||||
from htmlmodules import module_scrobblelist, module_pulse
|
||||
|
||||
|
||||
filterkeys, _, _, _ = KeySplit(keys,forceTrack=True)
|
||||
filterkeys, _, _, _ = uri_to_internal(keys,forceTrack=True)
|
||||
|
||||
track = filterkeys.get("track")
|
||||
imgurl = getTrackImage(track["artists"],track["title"],fast=True)
|
||||
@ -40,7 +41,7 @@ def instructions(keys):
|
||||
|
||||
|
||||
replace = {"KEY_TRACKTITLE":track.get("title"),"KEY_ARTISTS":artistLinks(track.get("artists")),"KEY_SCROBBLES":scrobblesnum,"KEY_POSITION":pos,"KEY_IMAGEURL":imgurl,
|
||||
"KEY_SCROBBLELINK":keysToUrl(keys),"KEY_MEDALS":html_medals,
|
||||
"KEY_SCROBBLELINK":compose_querystring(keys),"KEY_MEDALS":html_medals,
|
||||
"KEY_SCROBBLELIST":html_scrobbles,"KEY_PULSE":html_pulse}
|
||||
|
||||
return (replace,pushresources)
|
||||
|
Loading…
x
Reference in New Issue
Block a user