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:
commit
2c723e2586
330
database.py
330
database.py
@ -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
|
||||
|
18
utilities.py
18
utilities.py
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user