1
0
mirror of https://github.com/krateng/maloja.git synced 2023-08-10 21:12:55 +03:00

Implemented separation of database functions and their HTTP access methods

This commit is contained in:
Krateng 2019-02-17 15:54:56 +01:00
commit 2c723e2586
2 changed files with 255 additions and 93 deletions

View File

@ -114,9 +114,20 @@ def getTrackID(artists,title):
return i
####
## HTTP requests
####
########
########
## HTTP requests and their associated functions
########
########
@dbserver.route("/test")
def test_server():
@ -137,95 +148,174 @@ def test_server():
# 205 Database server is up, but DB is not fully built or is inconsistent
# 403 Database server is up, but provided API key is not valid
## All database functions are separated - the external wrapper only reads the request keys, converts them into lists and renames them where necessary, and puts the end result in a dict if not already so it can be returned as json
@dbserver.route("/scrobbles")
def get_scrobbles():
def get_scrobbles_external():
keys = FormsDict.decode(request.query)
ckeys = {}
ckeys["artists"], ckeys["title"] = keys.getall("artist"), keys.get("title")
ckeys["since"], ckeys["to"], ckeys["within"] = keys.get("since"), keys.get("to"), keys.get("in")
ckeys["associated"] = (keys.get("associated")!=None)
ckeys["max"] = keys.get("max")
r = db_query(artists=keys.getall("artist"),title=keys.get("title"),since=keys.get("since"),to=keys.get("to"),within=keys.get("in"),associated=(keys.get("associated")!=None))
result = get_scrobbles(**ckeys)
return {"list":result}
def get_scrobbles(**keys):
r = db_query(**{k:keys[k] for k in keys if k in ["artists","title","since","to","within","associated"]})
r.reverse()
if keys.get("max") is not None:
return {"list":r[:int(keys.get("max"))]}
return r[:int(keys.get("max"))]
else:
return {"list":r} ##json can't be a list apparently???
return r
# DEPRECATED
# UNUSED
@dbserver.route("/amounts")
def get_amounts_external():
return get_amounts() #really now
def get_amounts():
return {"scrobbles":len(SCROBBLES),"tracks":len(TRACKS),"artists":len(ARTISTS)}
@dbserver.route("/numscrobbles")
def get_scrobbles():
def get_scrobbles_num_external():
keys = FormsDict.decode(request.query)
ckeys = {}
ckeys["artists"], ckeys["title"] = keys.getall("artist"), keys.get("title")
ckeys["since"], ckeys["to"], ckeys["within"] = keys.get("since"), keys.get("to"), keys.get("in")
ckeys["associated"] = (keys.get("associated")!=None)
r = db_query(artists=keys.getall("artist"),title=keys.get("title"),since=keys.get("since"),to=keys.get("to"),within=keys.get("in"),associated=(keys.get("associated")!=None))
r.reverse()
result = get_scrobbles_num(**ckeys)
return {"amount":result}
def get_scrobbles_num(**keys):
r = db_query(**{k:keys[k] for k in keys if k in ["artists","title","since","to","within","associated"]})
return len(r)
# DEPRECATED
# UNUSED
@dbserver.route("/charts")
def get_charts_external():
keys = FormsDict.decode(request.query)
ckeys = {}
ckeys["since"], ckeys["to"], ckeys["within"] = keys.get("since"), keys.get("to"), keys.get("in")
result = get_scrobbles_num(**ckeys)
return {"number":result}
#def get_charts(**keys):
# return db_aggregate(**{k:keys[k] for k in keys if k in ["since","to","within"]})
return {"amount":len(r)}
@dbserver.route("/tracks")
def get_tracks():
def get_tracks_external():
keys = FormsDict.decode(request.query)
artist = keys.get("artist")
ckeys = {}
ckeys["artist"] = keys.get("artist")
result = get_tracks(**ckeys)
return {"list":result}
def get_tracks(artist=None):
if artist is not None:
artistid = ARTISTS.index(artist)
else:
artistid = None
# Option 1
ls = [getTrackObject(t) for t in TRACKS if (artistid in t[0]) or (artistid==None)]
return [getTrackObject(t) for t in TRACKS if (artistid in t[0]) or (artistid==None)]
# Option 2 is a bit more elegant but much slower
#tracklist = [getTrackObject(t) for t in TRACKS]
#ls = [t for t in tracklist if (artist in t["artists"]) or (artist==None)]
return {"list":ls}
@dbserver.route("/artists")
def get_artists_external():
result = get_artists()
return {"list":result}
def get_artists():
return ARTISTS #well
return {"list":ARTISTS}
@dbserver.route("/amounts")
def get_amounts():
return {"scrobbles":len(SCROBBLES),"tracks":len(TRACKS),"artists":len(ARTISTS)}
@dbserver.route("/charts/artists")
def get_charts_artists():
since = request.query.get("since")
to = request.query.get("to")
within=request.query.get("in")
return {"list":db_aggregate(by="ARTIST",since=since,to=to,within=within)}
@dbserver.route("/charts/tracks")
def get_charts_tracks():
def get_charts_artists_external():
keys = FormsDict.decode(request.query)
since = keys.get("since")
to = keys.get("to")
within=request.query.get("in")
artist = keys.get("artist")
ckeys = {}
ckeys["since"], ckeys["to"], ckeys["within"] = keys.get("since"), keys.get("to"), keys.get("in")
return {"list":db_aggregate(by="TRACK",since=since,to=to,within=within,artist=artist)}
result = get_charts_artists(**ckeys)
return {"list":result}
def get_charts_artists(**keys):
return db_aggregate(by="ARTIST",**{k:keys[k] for k in keys if k in ["since","to","within"]})
@dbserver.route("/charts/tracks")
def get_charts_tracks_external():
keys = FormsDict.decode(request.query)
ckeys = {}
ckeys["since"], ckeys["to"], ckeys["within"] = keys.get("since"), keys.get("to"), keys.get("in")
ckeys["artist"] = keys.get("artist")
@dbserver.route("/charts")
def get_charts():
since = request.query.get("since")
to = request.query.get("to")
within=request.query.get("in")
result = get_charts_tracks(**ckeys)
return {"list":result}
return {"number":db_aggregate(since=since,to=to,within=within)}
def get_charts_tracks(**keys):
return db_aggregate(by="TRACK",**{k:keys[k] for k in keys if k in ["since","to","within","artist"]})
@dbserver.route("/pulse")
def get_pulse():
since = request.query.get("since")
to = request.query.get("to")
within=request.query.get("in")
(ts_start,ts_end) = getTimestamps(since,to,within)
step = request.query.get("step","month")
trail = int(request.query.get("trail",3))
[step,stepn] = (step.split("-") + [1])[:2] # makes the multiplier 1 if not assigned
stepn = int(stepn)
def get_pulse_external():
keys = FormsDict.decode(request.query)
ckeys = {}
ckeys["since"], ckeys["to"], ckeys["within"] = keys.get("since"), keys.get("to"), keys.get("in")
ckeys["step"], ckeys["trail"] = keys.get("step"), int_or_none(keys.get("trail"))
if ckeys["step"] is not None: [ckeys["step"],ckeys["stepn"]] = (ckeys["step"].split("-") + [1])[:2] # makes the multiplier 1 if not assigned
if "stepn" in ckeys: ckeys["stepn"] = int(ckeys["stepn"])
cleandict(ckeys)
results = get_pulse(**ckeys)
return {"list":results}
def get_pulse(step="month",stepn=1,trail=3,**keys):
(ts_start,ts_end) = getTimestamps(**{k:keys[k] for k in keys if k in ["since","to","within"]})
d_start = getStartOf(ts_start,step)
d_end = getStartOf(ts_end,step)
d_start = getNext(d_start,step,stepn) # first range should end right after the first active scrobbling week / month / whatever relevant step
d_start = getNext(d_start,step,stepn * trail * -1) # go one range back to begin
@ -234,31 +324,40 @@ def get_pulse():
d_current = d_start
while True:
d_current_end = getNext(d_current,step,stepn * trail)
#print("Checking from " + str(d_current[0]) + "-" + str(d_current[1]) + "-" + str(d_current[2]) + " to " + str(d_current_end[0]) + "-" + str(d_current_end[1]) + "-" + str(d_current_end[2]))
res = db_aggregate(since=d_current,to=d_current_end)
results.append({"from":d_current,"to":d_current_end,"scrobbles":res})
d_current = getNext(d_current,step,stepn)
if isPast(d_current_end,d_end):
break
return {"list":results}
return results
@dbserver.route("/top/artists")
def get_top_artists():
since = request.query.get("since")
to = request.query.get("to")
within=request.query.get("in")
(ts_start,ts_end) = getTimestamps(since,to,within)
step = request.query.get("step","month")
trail = int(request.query.get("trail",3))
def get_top_artists_external():
keys = FormsDict.decode(request.query)
ckeys = {}
ckeys["since"], ckeys["to"], ckeys["within"] = keys.get("since"), keys.get("to"), keys.get("in")
ckeys["step"], ckeys["trail"] = keys.get("step"), int_or_none(keys.get("trail"))
if ckeys["step"] is not None: [ckeys["step"],ckeys["stepn"]] = (ckeys["step"].split("-") + [1])[:2] # makes the multiplier 1 if not assigned
if "stepn" in ckeys: ckeys["stepn"] = int(ckeys["stepn"])
[step,stepn] = (step.split("-") + [1])[:2] # makes the multiplier 1 if not assigned
stepn = int(stepn)
cleandict(ckeys)
results = get_top_artists(**ckeys)
return {"list":results}
def get_top_artists(step="month",stepn=1,trail=3,**keys):
(ts_start,ts_end) = getTimestamps(**{k:keys[k] for k in keys if k in ["since","to","within"]})
d_start = getStartOf(ts_start,step)
d_end = getStartOf(ts_end,step)
d_end = getStartOf(ts_end,step)
d_start = getNext(d_start,step,stepn) # first range should end right after the first active scrobbling week / month / whatever relevant step
d_start = getNext(d_start,step,stepn * trail * -1) # go one range back to begin
@ -267,7 +366,6 @@ def get_top_artists():
d_current = d_start
while True:
d_current_end = getNext(d_current,step,stepn * trail)
#print("Checking from " + str(d_current[0]) + "-" + str(d_current[1]) + "-" + str(d_current[2]) + " to " + str(d_current_end[0]) + "-" + str(d_current_end[1]) + "-" + str(d_current_end[2]))
try:
res = db_aggregate(since=d_current,to=d_current_end,by="ARTIST")[0]
results.append({"from":d_current,"to":d_current_end,"artist":res["artist"],"scrobbles":res["scrobbles"]})
@ -277,32 +375,44 @@ def get_top_artists():
if isPast(d_current_end,d_end):
break
return {"list":results}
return results
@dbserver.route("/top/tracks")
def get_top_tracks():
since = request.query.get("since")
to = request.query.get("to")
within=request.query.get("in")
(ts_start,ts_end) = getTimestamps(since,to,within)
step = request.query.get("step","month")
trail = int(request.query.get("trail",3))
[step,stepn] = (step.split("-") + [1])[:2] # makes the multiplier 1 if not assigned
stepn = int(stepn)
def get_top_tracks_external():
keys = FormsDict.decode(request.query)
ckeys = {}
ckeys["since"], ckeys["to"], ckeys["within"] = keys.get("since"), keys.get("to"), keys.get("in")
ckeys["step"], ckeys["trail"] = keys.get("step"), int_or_none(keys.get("trail"))
if ckeys["step"] is not None: [ckeys["step"],ckeys["stepn"]] = (ckeys["step"].split("-") + [1])[:2] # makes the multiplier 1 if not assigned
if "stepn" in ckeys: ckeys["stepn"] = int(ckeys["stepn"])
cleandict(ckeys)
results = get_top_tracks(**ckeys)
return {"list":results}
def get_top_tracks(step="month",stepn=1,trail=3,**keys):
(ts_start,ts_end) = getTimestamps(**{k:keys[k] for k in keys if k in ["since","to","within"]})
d_start = getStartOf(ts_start,step)
d_end = getStartOf(ts_end,step)
d_end = getStartOf(ts_end,step)
d_start = getNext(d_start,step,stepn) # first range should end right after the first active scrobbling week / month / whatever relevant step
d_start = getNext(d_start,step,stepn * trail * -1) # go one range back to begin
results = []
d_current = d_start
while True:
d_current_end = getNext(d_current,step,stepn * trail)
#print("Checking from " + str(d_current[0]) + "-" + str(d_current[1]) + "-" + str(d_current[2]) + " to " + str(d_current_end[0]) + "-" + str(d_current_end[1]) + "-" + str(d_current_end[2]))
try:
res = db_aggregate(since=d_current,to=d_current_end,by="TRACK")[0]
results.append({"from":d_current,"to":d_current_end,"track":res["track"],"scrobbles":res["scrobbles"]})
@ -312,7 +422,18 @@ def get_top_tracks():
if isPast(d_current_end,d_end):
break
return {"list":results}
return results
def getStartOf(timestamp,unit):
@ -356,10 +477,16 @@ def getNext(time,unit="auto",step=1):
elif unit == "week":
return getNext(time,"day",step * 7)
@dbserver.route("/artistinfo")
def artistInfo():
@dbserver.route("/artistinfo")
def artistInfo_external():
keys = FormsDict.decode(request.query)
artist = keys.get("artist")
ckeys = {}
ckeys["artist"] = keys.get("artist")
results = artistInfo(**ckeys)
return results
def artistInfo(artist):
charts = db_aggregate(by="ARTIST")
scrobbles = len(db_query(artists=[artist])) #we cant take the scrobble number from the charts because that includes all countas scrobbles
@ -372,19 +499,28 @@ def artistInfo():
artist = coa.getCredited(artist)
c = [e for e in charts if e["artist"] == artist][0]
return {"replace":artist,"scrobbles":scrobbles,"position":charts.index(c) + 1}
@dbserver.route("/trackinfo")
def trackInfo():
def trackInfo_external():
keys = FormsDict.decode(request.query)
artists = keys.getall("artist")
title = keys.get("title")
ckeys = {}
ckeys["artists"],ckeys["title"] = keys.getall("artist"), keys.get("title")
results = trackInfo(**ckeys)
return results
def trackInfo(artists,title):
charts = db_aggregate(by="TRACK")
scrobbles = len(db_query(artists=artists,title=title)) #we cant take the scrobble number from the charts because that includes all countas scrobbles
c = [e for e in charts if set(e["track"]["artists"]) == set(artists) and e["track"]["title"] == title][0]
return {"scrobbles":scrobbles,"position":charts.index(c) + 1}
def isPast(date,limit):
if not date[0] == limit[0]:
@ -393,6 +529,12 @@ def isPast(date,limit):
return date[1] > limit[1]
return (date[2] > limit[2])
@dbserver.get("/newscrobble")
def pseudo_post_scrobble():
keys = FormsDict.decode(request.query) # The Dal★Shabet handler
@ -766,7 +908,9 @@ def db_search(query,type=None):
# Takes user inputs like YYYY/MM and returns the timestamps. Returns timestamp if timestamp was already given.
# to dates are interpreted differently (from 2010 and to 2010 both include all of 2010)
def getTimestamps(f=None,t=None,i=None):
def getTimestamps(since=None,to=None,within=None):
f,t,i = since,to,within
if i is not None:
f = i

View File

@ -135,6 +135,24 @@ def addEntries(filename,al):
for a in al:
line = "\t".join(a)
f.write(line + "\n")
### Useful functions
def int_or_none(input_):
try:
return int(input_)
except:
return None
def cleandict(d):
newdict = {k:d[k] for k in d if d[k] is not None}
d.clear()
d.update(newdict)
### Logging