mirror of
https://github.com/krateng/maloja.git
synced 2023-08-10 21:12:55 +03:00
Merge branch 'timeobjects'
This commit is contained in:
commit
2935236f42
60
database.py
60
database.py
@ -15,6 +15,7 @@ import datetime
|
||||
import sys
|
||||
import unicodedata
|
||||
import json
|
||||
import pickle
|
||||
from collections import namedtuple
|
||||
from threading import Lock
|
||||
# url handling
|
||||
@ -210,7 +211,7 @@ def get_scrobbles_external():
|
||||
return {"list":result}
|
||||
|
||||
def get_scrobbles(**keys):
|
||||
r = db_query(**{k:keys[k] for k in keys if k in ["artist","artists","title","since","to","within","associated","track","max_"]})
|
||||
r = db_query(**{k:keys[k] for k in keys if k in ["artist","artists","title","since","to","within","timerange","associated","track","max_"]})
|
||||
#if keys.get("max_") is not None:
|
||||
# return r[:int(keys.get("max_"))]
|
||||
#else:
|
||||
@ -240,7 +241,7 @@ def get_scrobbles_num_external():
|
||||
return {"amount":result}
|
||||
|
||||
def get_scrobbles_num(**keys):
|
||||
r = db_query(**{k:keys[k] for k in keys if k in ["artist","track","artists","title","since","to","within","associated"]})
|
||||
r = db_query(**{k:keys[k] for k in keys if k in ["artist","track","artists","title","since","to","within","timerange","associated"]})
|
||||
return len(r)
|
||||
|
||||
|
||||
@ -343,7 +344,7 @@ def get_charts_artists_external():
|
||||
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"]})
|
||||
return db_aggregate(by="ARTIST",**{k:keys[k] for k in keys if k in ["since","to","within","timerange"]})
|
||||
|
||||
|
||||
|
||||
@ -360,7 +361,7 @@ def get_charts_tracks_external():
|
||||
return {"list":result}
|
||||
|
||||
def get_charts_tracks(**keys):
|
||||
return db_aggregate(by="TRACK",**{k:keys[k] for k in keys if k in ["since","to","within","artist"]})
|
||||
return db_aggregate(by="TRACK",**{k:keys[k] for k in keys if k in ["since","to","within","timerange","artist"]})
|
||||
|
||||
|
||||
|
||||
@ -381,12 +382,11 @@ def get_pulse_external():
|
||||
|
||||
def get_pulse(**keys):
|
||||
|
||||
rngs = ranges(**{k:keys[k] for k in keys if k in ["since","to","within","step","stepn","trail"]})
|
||||
rngs = ranges(**{k:keys[k] for k in keys if k in ["since","to","within","timerange","step","stepn","trail"]})
|
||||
results = []
|
||||
|
||||
for (a,b) in rngs:
|
||||
res = len(db_query(since=a,to=b,**{k:keys[k] for k in keys if k in ["artists","artist","track","title","associated"]}))
|
||||
results.append({"from":a,"to":b,"scrobbles":res})
|
||||
for rng in rngs:
|
||||
res = len(db_query(timerange=rng,**{k:keys[k] for k in keys if k in ["artists","artist","track","title","associated"]}))
|
||||
results.append({"range":rng,"scrobbles":res})
|
||||
|
||||
return results
|
||||
|
||||
@ -405,25 +405,25 @@ def get_performance_external():
|
||||
|
||||
def get_performance(**keys):
|
||||
|
||||
rngs = ranges(**{k:keys[k] for k in keys if k in ["since","to","within","step","stepn","trail"]})
|
||||
rngs = ranges(**{k:keys[k] for k in keys if k in ["since","to","within","timerange","step","stepn","trail"]})
|
||||
results = []
|
||||
|
||||
for (a,b) in rngs:
|
||||
for rng in rngs:
|
||||
if "track" in keys:
|
||||
charts = get_charts_tracks(since=a,to=b)
|
||||
charts = get_charts_tracks(timerange=rng)
|
||||
rank = None
|
||||
for c in charts:
|
||||
if c["track"] == keys["track"]:
|
||||
rank = c["rank"]
|
||||
break
|
||||
elif "artist" in keys:
|
||||
charts = get_charts_artists(since=a,to=b)
|
||||
charts = get_charts_artists(timerange=rng)
|
||||
rank = None
|
||||
for c in charts:
|
||||
if c["artist"] == keys["artist"]:
|
||||
rank = c["rank"]
|
||||
break
|
||||
results.append({"from":a,"to":b,"rank":rank})
|
||||
results.append({"range":rng,"rank":rank})
|
||||
|
||||
return results
|
||||
|
||||
@ -446,15 +446,15 @@ def get_top_artists_external():
|
||||
|
||||
def get_top_artists(**keys):
|
||||
|
||||
rngs = ranges(**{k:keys[k] for k in keys if k in ["since","to","within","step","stepn","trail"]})
|
||||
rngs = ranges(**{k:keys[k] for k in keys if k in ["since","to","within","timerange","step","stepn","trail"]})
|
||||
results = []
|
||||
|
||||
for (a,b) in rngs:
|
||||
for rng in rngs:
|
||||
try:
|
||||
res = db_aggregate(since=a,to=b,by="ARTIST")[0]
|
||||
results.append({"since":a,"to":b,"artist":res["artist"],"counting":res["counting"],"scrobbles":res["scrobbles"]})
|
||||
res = db_aggregate(timerange=rng,by="ARTIST")[0]
|
||||
results.append({"range":rng,"artist":res["artist"],"counting":res["counting"],"scrobbles":res["scrobbles"]})
|
||||
except:
|
||||
results.append({"since":a,"to":b,"artist":None,"scrobbles":0})
|
||||
results.append({"range":rng,"artist":None,"scrobbles":0})
|
||||
|
||||
return results
|
||||
|
||||
@ -480,15 +480,15 @@ def get_top_tracks_external():
|
||||
|
||||
def get_top_tracks(**keys):
|
||||
|
||||
rngs = ranges(**{k:keys[k] for k in keys if k in ["since","to","within","step","stepn","trail"]})
|
||||
rngs = ranges(**{k:keys[k] for k in keys if k in ["since","to","within","timerange","step","stepn","trail"]})
|
||||
results = []
|
||||
|
||||
for (a,b) in rngs:
|
||||
try:
|
||||
res = db_aggregate(since=a,to=b,by="TRACK")[0]
|
||||
results.append({"since":a,"to":b,"track":res["track"],"scrobbles":res["scrobbles"]})
|
||||
res = db_aggregate(timerange=rng,by="TRACK")[0]
|
||||
results.append({"range":rng,"track":res["track"],"scrobbles":res["scrobbles"]})
|
||||
except:
|
||||
results.append({"since":a,"to":b,"track":None,"scrobbles":0})
|
||||
results.append({"range":rng,"track":None,"scrobbles":0})
|
||||
|
||||
return results
|
||||
|
||||
@ -900,7 +900,7 @@ cacheday = (0,0,0)
|
||||
def db_query(**kwargs):
|
||||
check_cache_age()
|
||||
global cache_query
|
||||
key = json.dumps(kwargs)
|
||||
key = pickle.dumps(kwargs)
|
||||
if key in cache_query: return copy.copy(cache_query[key])
|
||||
|
||||
result = db_query_full(**kwargs)
|
||||
@ -911,7 +911,7 @@ cache_aggregate = {}
|
||||
def db_aggregate(**kwargs):
|
||||
check_cache_age()
|
||||
global cache_aggregate
|
||||
key = json.dumps(kwargs)
|
||||
key = pickle.dumps(kwargs)
|
||||
if key in cache_aggregate: return copy.copy(cache_aggregate[key])
|
||||
|
||||
result = db_aggregate_full(**kwargs)
|
||||
@ -942,9 +942,9 @@ def check_cache_age():
|
||||
|
||||
|
||||
# Queries the database
|
||||
def db_query_full(artist=None,artists=None,title=None,track=None,since=None,to=None,within=None,associated=False,max_=None):
|
||||
def db_query_full(artist=None,artists=None,title=None,track=None,since=None,to=None,within=None,timerange=None,associated=False,max_=None):
|
||||
|
||||
(since, to) = time_stamps(since,to,within)
|
||||
(since, to) = time_stamps(since=since,to=to,within=within,range=timerange)
|
||||
|
||||
# this is not meant as a search function. we *can* query the db with a string, but it only works if it matches exactly
|
||||
# if a title is specified, we assume that a specific track (with the exact artist combination) is requested
|
||||
@ -993,8 +993,10 @@ def db_query_full(artist=None,artists=None,title=None,track=None,since=None,to=N
|
||||
|
||||
|
||||
# Queries that... well... aggregate
|
||||
def db_aggregate_full(by=None,since=None,to=None,within=None,artist=None):
|
||||
(since, to) = time_stamps(since,to,within)
|
||||
def db_aggregate_full(by=None,since=None,to=None,within=None,timerange=None,artist=None):
|
||||
|
||||
|
||||
(since, to) = time_stamps(since=since,to=to,within=within,range=timerange)
|
||||
|
||||
if isinstance(artist, str):
|
||||
artist = ARTISTS.index(artist)
|
||||
|
136
htmlmodules.py
136
htmlmodules.py
@ -5,6 +5,7 @@ from malojatime import *
|
||||
from urihandler import compose_querystring, internal_to_uri, uri_to_internal
|
||||
import urllib
|
||||
import datetime
|
||||
import math
|
||||
|
||||
|
||||
#def getpictures(ls,result,tracks=False):
|
||||
@ -21,7 +22,7 @@ import datetime
|
||||
def module_scrobblelist(max_=None,pictures=False,shortTimeDesc=False,earlystop=False,**kwargs):
|
||||
|
||||
kwargs_filter = pickKeys(kwargs,"artist","track","associated")
|
||||
kwargs_time = pickKeys(kwargs,"since","to","within")
|
||||
kwargs_time = pickKeys(kwargs,"timerange","since","to","within")
|
||||
|
||||
|
||||
# if earlystop, we don't care about the actual amount and only request as many from the db
|
||||
@ -42,7 +43,7 @@ def module_scrobblelist(max_=None,pictures=False,shortTimeDesc=False,earlystop=F
|
||||
for s in scrobbles:
|
||||
|
||||
html += "<tr>"
|
||||
html += "<td class='time'>" + time_desc(s["time"],short=shortTimeDesc) + "</td>"
|
||||
html += "<td class='time'>" + timestamp_desc(s["time"],short=shortTimeDesc) + "</td>"
|
||||
if pictures:
|
||||
img = scrobbleimages[i]
|
||||
else: img = None
|
||||
@ -63,11 +64,15 @@ def module_scrobblelist(max_=None,pictures=False,shortTimeDesc=False,earlystop=F
|
||||
|
||||
def module_pulse(max_=None,**kwargs):
|
||||
|
||||
from doreah.timing import clock, clockp
|
||||
|
||||
kwargs_filter = pickKeys(kwargs,"artist","track","associated")
|
||||
kwargs_time = pickKeys(kwargs,"since","to","within","step","stepn","trail")
|
||||
kwargs_time = pickKeys(kwargs,"since","to","within","timerange","step","stepn","trail")
|
||||
|
||||
|
||||
ranges = database.get_pulse(**kwargs_time,**kwargs_filter)
|
||||
|
||||
|
||||
if max_ is not None: ranges = ranges[:max_]
|
||||
|
||||
# if time range not explicitly specified, only show from first appearance
|
||||
@ -81,12 +86,11 @@ def module_pulse(max_=None,**kwargs):
|
||||
#build list
|
||||
html = "<table class='list'>"
|
||||
for t in ranges:
|
||||
fromstr = "/".join([str(e) for e in t["from"]])
|
||||
tostr = "/".join([str(e) for e in t["to"]])
|
||||
range = t["range"]
|
||||
html += "<tr>"
|
||||
html += "<td>" + range_desc(t["from"],t["to"],short=True) + "</td>"
|
||||
html += "<td class='amount'>" + scrobblesLink({"since":fromstr,"to":tostr},amount=t["scrobbles"],**kwargs_filter) + "</td>"
|
||||
html += "<td class='bar'>" + scrobblesLink({"since":fromstr,"to":tostr},percent=t["scrobbles"]*100/maxbar,**kwargs_filter) + "</td>"
|
||||
html += "<td>" + range.desc() + "</td>"
|
||||
html += "<td class='amount'>" + scrobblesLink(range.urikeys(),amount=t["scrobbles"],**kwargs_filter) + "</td>"
|
||||
html += "<td class='bar'>" + scrobblesLink(range.urikeys(),percent=t["scrobbles"]*100/maxbar,**kwargs_filter) + "</td>"
|
||||
html += "</tr>"
|
||||
html += "</table>"
|
||||
|
||||
@ -98,7 +102,7 @@ def module_pulse(max_=None,**kwargs):
|
||||
def module_performance(max_=None,**kwargs):
|
||||
|
||||
kwargs_filter = pickKeys(kwargs,"artist","track")
|
||||
kwargs_time = pickKeys(kwargs,"since","to","within","step","stepn","trail")
|
||||
kwargs_time = pickKeys(kwargs,"since","to","within","timerange","step","stepn","trail")
|
||||
|
||||
ranges = database.get_performance(**kwargs_time,**kwargs_filter)
|
||||
|
||||
@ -117,13 +121,12 @@ def module_performance(max_=None,**kwargs):
|
||||
#build list
|
||||
html = "<table class='list'>"
|
||||
for t in ranges:
|
||||
fromstr = "/".join([str(e) for e in t["from"]])
|
||||
tostr = "/".join([str(e) for e in t["to"]])
|
||||
range = t["range"]
|
||||
html += "<tr>"
|
||||
html += "<td>" + range_desc(t["from"],t["to"],short=True) + "</td>"
|
||||
html += "<td>" + range.desc() + "</td>"
|
||||
html += "<td class='rank'>" + ("#" + str(t["rank"]) if t["rank"] is not None else "No scrobbles") + "</td>"
|
||||
prct = (minrank+1-t["rank"])*100/minrank if t["rank"] is not None else 0
|
||||
html += "<td class='chart'>" + rankLink({"since":fromstr,"to":tostr},percent=prct,**kwargs_filter,medal=t["rank"]) + "</td>"
|
||||
html += "<td class='chart'>" + rankLink(range.urikeys(),percent=prct,**kwargs_filter,medal=t["rank"]) + "</td>"
|
||||
html += "</tr>"
|
||||
html += "</table>"
|
||||
|
||||
@ -135,14 +138,13 @@ def module_performance(max_=None,**kwargs):
|
||||
def module_trackcharts(max_=None,**kwargs):
|
||||
|
||||
kwargs_filter = pickKeys(kwargs,"artist","associated")
|
||||
kwargs_time = pickKeys(kwargs,"since","to","within")
|
||||
kwargs_time = pickKeys(kwargs,"timerange","since","to","within")
|
||||
|
||||
tracks = database.get_charts_tracks(**kwargs_filter,**kwargs_time)
|
||||
|
||||
# last time range (to compare)
|
||||
if "within" in kwargs_time:
|
||||
from malojatime import _get_next
|
||||
trackslast = database.get_charts_tracks(**kwargs_filter,within=_get_next(kwargs_time["within"],step=-1))
|
||||
try:
|
||||
trackslast = database.get_charts_tracks(**kwargs_filter,timerange=kwargs_time["timerange"].next(step=-1))
|
||||
# create rank association
|
||||
lastrank = {}
|
||||
for tl in trackslast:
|
||||
@ -151,7 +153,9 @@ def module_trackcharts(max_=None,**kwargs):
|
||||
try:
|
||||
t["delta"] = lastrank[(*t["track"]["artists"],t["track"]["title"])] - t["rank"]
|
||||
except:
|
||||
t["delta"] = None
|
||||
t["delta"] = math.inf
|
||||
except:
|
||||
pass
|
||||
|
||||
if tracks != []:
|
||||
maxbar = tracks[0]["scrobbles"]
|
||||
@ -173,8 +177,9 @@ def module_trackcharts(max_=None,**kwargs):
|
||||
else:
|
||||
html += "<td class='rank'></td>"
|
||||
# rank change
|
||||
if "within" not in kwargs_time: pass
|
||||
elif e["delta"] is None:
|
||||
if e.get("delta") is None:
|
||||
pass
|
||||
elif e["delta"] is math.inf:
|
||||
html += "<td class='rankup' title='New'>🆕</td>"
|
||||
elif e["delta"] > 0:
|
||||
html += "<td class='rankup' title='up from #" + str(e["rank"]+e["delta"]) + "'>↗</td>"
|
||||
@ -197,14 +202,14 @@ def module_trackcharts(max_=None,**kwargs):
|
||||
def module_artistcharts(max_=None,**kwargs):
|
||||
|
||||
kwargs_filter = pickKeys(kwargs,"associated") #not used right now
|
||||
kwargs_time = pickKeys(kwargs,"since","to","within")
|
||||
kwargs_time = pickKeys(kwargs,"timerange","since","to","within")
|
||||
|
||||
artists = database.get_charts_artists(**kwargs_filter,**kwargs_time)
|
||||
|
||||
# last time range (to compare)
|
||||
if "within" in kwargs_time:
|
||||
from malojatime import _get_next
|
||||
artistslast = database.get_charts_artists(**kwargs_filter,within=_get_next(kwargs_time["within"],step=-1))
|
||||
try:
|
||||
#from malojatime import _get_next
|
||||
artistslast = database.get_charts_artists(**kwargs_filter,timerange=kwargs_time["timerange"].next(step=-1))
|
||||
# create rank association
|
||||
lastrank = {}
|
||||
for al in artistslast:
|
||||
@ -213,7 +218,9 @@ def module_artistcharts(max_=None,**kwargs):
|
||||
try:
|
||||
a["delta"] = lastrank[a["artist"]] - a["rank"]
|
||||
except:
|
||||
a["delta"] = None
|
||||
a["delta"] = math.inf
|
||||
except:
|
||||
pass
|
||||
|
||||
if artists != []:
|
||||
maxbar = artists[0]["scrobbles"]
|
||||
@ -234,8 +241,10 @@ def module_artistcharts(max_=None,**kwargs):
|
||||
else:
|
||||
html += "<td class='rank'></td>"
|
||||
# rank change
|
||||
if "within" not in kwargs_time: pass
|
||||
elif e["delta"] is None:
|
||||
#if "within" not in kwargs_time: pass
|
||||
if e.get("delta") is None:
|
||||
pass
|
||||
elif e["delta"] is math.inf:
|
||||
html += "<td class='rankup' title='New'>🆕</td>"
|
||||
elif e["delta"] > 0:
|
||||
html += "<td class='rankup' title='up from #" + str(e["rank"]+e["delta"]) + "'>↗</td>"
|
||||
@ -260,7 +269,7 @@ def module_artistcharts(max_=None,**kwargs):
|
||||
def module_toptracks(pictures=True,**kwargs):
|
||||
|
||||
kwargs_filter = pickKeys(kwargs,"artist","associated")
|
||||
kwargs_time = pickKeys(kwargs,"since","to","within","step","stepn","trail")
|
||||
kwargs_time = pickKeys(kwargs,"timerange","since","to","within","step","stepn","trail")
|
||||
|
||||
tracks = database.get_top_tracks(**kwargs_filter,**kwargs_time)
|
||||
|
||||
@ -288,13 +297,13 @@ def module_toptracks(pictures=True,**kwargs):
|
||||
|
||||
#fromstr = "/".join([str(p) for p in e["from"]])
|
||||
#tostr = "/".join([str(p) for p in e["to"]])
|
||||
limits = pickKeys(e,"since","to")
|
||||
range = e["range"]
|
||||
|
||||
i += 1
|
||||
html += "<tr>"
|
||||
|
||||
|
||||
html += "<td>" + range_desc(e["since"],e["to"],short=True) + "</td>"
|
||||
html += "<td>" + range.desc() + "</td>"
|
||||
if e["track"] is None:
|
||||
if pictures:
|
||||
html += "<td><div></div></td>"
|
||||
@ -307,8 +316,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"],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 += "<td class='amount'>" + scrobblesTrackLink(e["track"],range.urikeys(),amount=e["scrobbles"]) + "</td>"
|
||||
html += "<td class='bar'>" + scrobblesTrackLink(e["track"],range.urikeys(),percent=e["scrobbles"]*100/maxbar) + "</td>"
|
||||
html += "</tr>"
|
||||
prev = e
|
||||
html += "</table>"
|
||||
@ -317,7 +326,7 @@ def module_toptracks(pictures=True,**kwargs):
|
||||
|
||||
def module_topartists(pictures=True,**kwargs):
|
||||
|
||||
kwargs_time = pickKeys(kwargs,"since","to","within","step","stepn","trail")
|
||||
kwargs_time = pickKeys(kwargs,"timerange","since","to","within","step","stepn","trail")
|
||||
|
||||
artists = database.get_top_artists(**kwargs_time)
|
||||
|
||||
@ -344,13 +353,13 @@ def module_topartists(pictures=True,**kwargs):
|
||||
|
||||
#fromstr = "/".join([str(p) for p in e["from"]])
|
||||
#tostr = "/".join([str(p) for p in e["to"]])
|
||||
limits = pickKeys(e,"since","to")
|
||||
range = e["range"]
|
||||
|
||||
i += 1
|
||||
html += "<tr>"
|
||||
|
||||
|
||||
html += "<td>" + range_desc(e["since"],e["to"],short=True) + "</td>"
|
||||
html += "<td>" + range.desc() + "</td>"
|
||||
|
||||
if e["artist"] is None:
|
||||
if pictures:
|
||||
@ -363,8 +372,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"],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 += "<td class='amount'>" + scrobblesArtistLink(e["artist"],range.urikeys(),amount=e["scrobbles"],associated=True) + "</td>"
|
||||
html += "<td class='bar'>" + scrobblesArtistLink(e["artist"],range.urikeys(),percent=e["scrobbles"]*100/maxbar,associated=True) + "</td>"
|
||||
html += "</tr>"
|
||||
prev = e
|
||||
html += "</table>"
|
||||
@ -375,7 +384,7 @@ def module_topartists(pictures=True,**kwargs):
|
||||
def module_artistcharts_tiles(**kwargs):
|
||||
|
||||
kwargs_filter = pickKeys(kwargs,"associated") #not used right now
|
||||
kwargs_time = pickKeys(kwargs,"since","to","within")
|
||||
kwargs_time = pickKeys(kwargs,"timerange","since","to","within")
|
||||
|
||||
artists = database.get_charts_artists(**kwargs_filter,**kwargs_time)[:14]
|
||||
while len(artists)<14: artists.append(None)
|
||||
@ -423,7 +432,7 @@ def module_artistcharts_tiles(**kwargs):
|
||||
def module_trackcharts_tiles(**kwargs):
|
||||
|
||||
kwargs_filter = pickKeys(kwargs,"artist","associated")
|
||||
kwargs_time = pickKeys(kwargs,"since","to","within")
|
||||
kwargs_time = pickKeys(kwargs,"timerange","since","to","within")
|
||||
|
||||
tracks = database.get_charts_tracks(**kwargs_filter,**kwargs_time)[:14]
|
||||
while len(tracks)<14: tracks.append(None) #{"track":{"title":"","artists":[]}}
|
||||
@ -501,47 +510,44 @@ def module_filterselection(keys,time=True,delimit=False):
|
||||
# html += "to <input id='dateselect_to' onchange='datechange()' type='date' value='" + "-".join(todate) + "'/>"
|
||||
# html += "</div>"
|
||||
|
||||
|
||||
now = datetime.datetime.utcnow()
|
||||
today = [now.year,now.month,now.day]
|
||||
thismonth = today[:2]
|
||||
thisyear = thismonth[:1]
|
||||
from malojatime import today, thisweek, thismonth, thisyear
|
||||
|
||||
### temp!!! this will not allow weekly rank changes
|
||||
weekday = ((now.isoweekday()) % 7)
|
||||
weekbegin = now - datetime.timedelta(days=weekday)
|
||||
weekend = weekbegin + datetime.timedelta(days=6)
|
||||
weekbegin = [weekbegin.year,weekbegin.month,weekbegin.day]
|
||||
weekend = [weekend.year,weekend.month,weekend.day]
|
||||
weekbeginstr = "/".join((str(num) for num in weekbegin))
|
||||
weekendstr = "/".join((str(num) for num in weekend))
|
||||
# weekday = ((now.isoweekday()) % 7)
|
||||
# weekbegin = now - datetime.timedelta(days=weekday)
|
||||
# weekend = weekbegin + datetime.timedelta(days=6)
|
||||
# weekbegin = [weekbegin.year,weekbegin.month,weekbegin.day]
|
||||
# weekend = [weekend.year,weekend.month,weekend.day]
|
||||
# weekbeginstr = "/".join((str(num) for num in weekbegin))
|
||||
# weekendstr = "/".join((str(num) for num in weekend))
|
||||
|
||||
|
||||
html += "<div>"
|
||||
if timekeys.get("since") == today or timekeys.get("within") == today:
|
||||
if timekeys.get("timerange") == today():
|
||||
html += "<span class='stat_selector' style='opacity:0.5;'>Today</span>"
|
||||
else:
|
||||
html += "<a href='?" + compose_querystring(unchangedkeys,{"in":"today"}) + "'><span class='stat_selector'>Today</span></a>"
|
||||
html += " | "
|
||||
|
||||
if timekeys.get("since") == weekbegin and timekeys.get("to") == weekend:
|
||||
if timekeys.get("timerange") == thisweek():
|
||||
html += "<span class='stat_selector' style='opacity:0.5;'>This Week</span>"
|
||||
else:
|
||||
html += "<a href='?" + compose_querystring(unchangedkeys,{"since":weekbeginstr,"to":weekendstr}) + "'><span class='stat_selector'>This Week</span></a>"
|
||||
html += "<a href='?" + compose_querystring(unchangedkeys,{"in":"week"}) + "'><span class='stat_selector'>This Week</span></a>"
|
||||
html += " | "
|
||||
|
||||
if timekeys.get("since") == thismonth or timekeys.get("within") == thismonth:
|
||||
if timekeys.get("timerange") == thismonth():
|
||||
html += "<span class='stat_selector' style='opacity:0.5;'>This Month</span>"
|
||||
else:
|
||||
html += "<a href='?" + compose_querystring(unchangedkeys,{"in":"month"}) + "'><span class='stat_selector'>This Month</span></a>"
|
||||
html += " | "
|
||||
|
||||
if timekeys.get("since") == thisyear or timekeys.get("within") == thisyear:
|
||||
if timekeys.get("timerange") == thisyear():
|
||||
html += "<span class='stat_selector' style='opacity:0.5;'>This Year</span>"
|
||||
else:
|
||||
html += "<a href='?" + compose_querystring(unchangedkeys,{"in":"year"}) + "'><span class='stat_selector'>This Year</span></a>"
|
||||
html += " | "
|
||||
|
||||
if timekeys.get("since") is None and timekeys.get("within") is None:
|
||||
if timekeys.get("timerange") is None or timekeys.get("timerange").unlimited():
|
||||
html += "<span class='stat_selector' style='opacity:0.5;'>All Time</span>"
|
||||
else:
|
||||
html += "<a href='?" + compose_querystring(unchangedkeys) + "'><span class='stat_selector'>All Time</span></a>"
|
||||
@ -563,7 +569,13 @@ def module_filterselection(keys,time=True,delimit=False):
|
||||
html += "<a href='?" + compose_querystring(unchangedkeys,unchangedkeys_sub,{"step":"day"}) + "'><span class='stat_selector'>Daily</span></a>"
|
||||
html += " | "
|
||||
|
||||
if (delimitkeys.get("step") == "month" or delimitkeys.get("step") is None) and delimitkeys.get("stepn") == 1:
|
||||
if delimitkeys.get("step") == "week" and delimitkeys.get("stepn") == 1:
|
||||
html += "<span class='stat_selector' style='opacity:0.5;'>Weekly</span>"
|
||||
else:
|
||||
html += "<a href='?" + compose_querystring(unchangedkeys,unchangedkeys_sub,{"step":"week"}) + "'><span class='stat_selector'>Weekly</span></a>"
|
||||
html += " | "
|
||||
|
||||
if delimitkeys.get("step") == "month" and delimitkeys.get("stepn") == 1:
|
||||
html += "<span class='stat_selector' style='opacity:0.5;'>Monthly</span>"
|
||||
else:
|
||||
html += "<a href='?" + compose_querystring(unchangedkeys,unchangedkeys_sub,{"step":"month"}) + "'><span class='stat_selector'>Monthly</span></a>"
|
||||
@ -581,7 +593,7 @@ def module_filterselection(keys,time=True,delimit=False):
|
||||
unchangedkeys_sub = internal_to_uri({k:delimitkeys[k] for k in delimitkeys if k != "trail"})
|
||||
|
||||
html += "<div>"
|
||||
if delimitkeys.get("trail") == 1 or delimitkeys.get("trail") is None:
|
||||
if delimitkeys.get("trail") == 1:
|
||||
html += "<span class='stat_selector' style='opacity:0.5;'>Standard</span>"
|
||||
else:
|
||||
html += "<a href='?" + compose_querystring(unchangedkeys,unchangedkeys_sub,{"trail":"1"}) + "'><span class='stat_selector'>Standard</span></a>"
|
||||
@ -597,6 +609,12 @@ def module_filterselection(keys,time=True,delimit=False):
|
||||
html += "<span class='stat_selector' style='opacity:0.5;'>Long Trailing</span>"
|
||||
else:
|
||||
html += "<a href='?" + compose_querystring(unchangedkeys,unchangedkeys_sub,{"trail":"3"}) + "'><span class='stat_selector'>Long Trailing</span></a>"
|
||||
html += " | "
|
||||
|
||||
if delimitkeys.get("trail") == math.inf:
|
||||
html += "<span class='stat_selector' style='opacity:0.5;'>Cumulative</span>"
|
||||
else:
|
||||
html += "<a href='?" + compose_querystring(unchangedkeys,unchangedkeys_sub,{"cumulative":"yes"}) + "'><span class='stat_selector'>Cumulative</span></a>"
|
||||
|
||||
html += "</div>"
|
||||
|
||||
|
799
malojatime.py
799
malojatime.py
@ -1,6 +1,7 @@
|
||||
import datetime
|
||||
from calendar import monthrange
|
||||
from os.path import commonprefix
|
||||
import math
|
||||
|
||||
|
||||
FIRST_SCROBBLE = int(datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).timestamp())
|
||||
@ -32,12 +33,337 @@ def end_of_scrobbling():
|
||||
# return str(t)
|
||||
|
||||
|
||||
### helpers
|
||||
|
||||
# adjusting to sunday-first calendar
|
||||
# damn iso heathens
|
||||
class expandeddate(datetime.date):
|
||||
|
||||
def chrweekday(self):
|
||||
return self.isoweekday() + 1 % 7
|
||||
|
||||
def chrcalendar(self):
|
||||
tomorrow = self + datetime.timedelta(days=1)
|
||||
cal = tomorrow.isocalendar()
|
||||
return (cal[0],cal[1],cal[2] % 7)
|
||||
|
||||
date = expandeddate
|
||||
|
||||
|
||||
|
||||
|
||||
### EVERYTHING NEW AGAIN
|
||||
|
||||
# only for ranges, timestamps are separate
|
||||
|
||||
class MRangeDescriptor:
|
||||
|
||||
def __eq__(self,other):
|
||||
if not isinstance(other,MRangeDescriptor): return False
|
||||
return (self.first_stamp() == other.first_stamp() and self.last_stamp() == other.last_stamp())
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.first_stamp(),self.last_stamp()))
|
||||
|
||||
def info(self):
|
||||
return {
|
||||
"fromstring":self.fromstr(),
|
||||
"tostr":self.tostr(),
|
||||
"uri":self.uri(),
|
||||
"fromstamp":self.first_stamp(),
|
||||
"tostamp":self.last_stamp(),
|
||||
"description":self.desc()
|
||||
}
|
||||
|
||||
def uri(self):
|
||||
return "&".join(k + "=" + self.urikeys[k] for k in self.urikeys)
|
||||
|
||||
def unlimited(self):
|
||||
return False
|
||||
|
||||
|
||||
# a range that is exactly a gregorian calendar unit (year, month or day)
|
||||
class MTime(MRangeDescriptor):
|
||||
def __init__(self,*ls):
|
||||
# in case we want to call with non-unpacked arguments
|
||||
if isinstance(ls[0],tuple) or isinstance(ls[0],list):
|
||||
ls = ls[0]
|
||||
|
||||
self.tup = tuple(ls)
|
||||
self.precision = len(ls)
|
||||
self.year = ls[0]
|
||||
if len(ls)>1: self.month = ls[1]
|
||||
if len(ls)>2: self.day = ls[2]
|
||||
dt = [1970,1,1]
|
||||
dt[:len(ls)] = ls
|
||||
self.dateobject = date(dt[0],dt[1],dt[2])
|
||||
|
||||
def __str__(self):
|
||||
return "/".join(str(part) for part in self.tup)
|
||||
def fromstr(self):
|
||||
return str(self)
|
||||
def tostr(self):
|
||||
return str(self)
|
||||
|
||||
def urikeys(self):
|
||||
return {"in":str(self)}
|
||||
|
||||
def desc(self,prefix=False):
|
||||
if self.precision == 3:
|
||||
if prefix:
|
||||
return "on " + self.dateobject.strftime("%d. %B %Y")
|
||||
else:
|
||||
return self.dateobject.strftime("%d. %B %Y")
|
||||
if self.precision == 2:
|
||||
if prefix:
|
||||
return "in " + self.dateobject.strftime("%B %Y")
|
||||
else:
|
||||
return self.dateobject.strftime("%B %Y")
|
||||
if self.precision == 1:
|
||||
if prefix:
|
||||
return "in " + self.dateobject.strftime("%Y")
|
||||
else:
|
||||
return self.dateobject.strftime("%Y")
|
||||
|
||||
def informal_desc(self):
|
||||
now = datetime.datetime.now(tz=datetime.timezone.utc)
|
||||
today = date(now.year,now.month,now.day)
|
||||
if self.precision == 3:
|
||||
diff = (today - dateobject).days
|
||||
if diff == 0: return "Today"
|
||||
if diff == 1: return "Yesterday"
|
||||
if diff < 7 and diff > 1: return timeobject.strftime("%A")
|
||||
#elif len(t) == 2:
|
||||
return self.desc()
|
||||
|
||||
# describes only the parts that are different than another range object
|
||||
def contextual_desc(self,other):
|
||||
if isinstance(other,MTime):
|
||||
relevant = self.desc().split(" ")
|
||||
if self.year == other.year:
|
||||
relevant.pop()
|
||||
if self.precision > 1 and other.precision > 1 and self.month == other.month:
|
||||
relevant.pop()
|
||||
if self.precision > 2 and other.precision > 2 and self.day == other.day:
|
||||
relevant.pop()
|
||||
return " ".join(relevant)
|
||||
return self.desc()
|
||||
|
||||
# gets object with one higher precision that starts this one
|
||||
def start(self):
|
||||
if self.precision == 1: return MTime(self.tup + (1,))
|
||||
elif self.precision == 2: return MTime(self.tup + (1,))
|
||||
# gets object with one higher precision that ends this one
|
||||
def end(self):
|
||||
if self.precision == 1: return MTime(self.tup + (12,))
|
||||
elif self.precision == 2: return MTime(self.tup + (monthrange(self.year,self.month)[1],))
|
||||
|
||||
def first_day(self):
|
||||
if self.precision == 3: return self
|
||||
else: return self.start().first_day()
|
||||
def last_day(self):
|
||||
if self.precision == 3: return self
|
||||
else: return self.end().last_day()
|
||||
|
||||
def first_stamp(self):
|
||||
day = self.first_day().dateobject
|
||||
return int(datetime.datetime.combine(day,datetime.time(tzinfo=datetime.timezone.utc)).timestamp())
|
||||
def last_stamp(self):
|
||||
day = self.last_day().dateobject + datetime.timedelta(days=1)
|
||||
return int(datetime.datetime.combine(day,datetime.time(tzinfo=datetime.timezone.utc)).timestamp() - 1)
|
||||
|
||||
# next range of equal length (not exactly same amount of days, but same precision level)
|
||||
def next(self,step=1):
|
||||
if abs(step) == math.inf: return None
|
||||
if self.precision == 1:
|
||||
return MTime(self.year + step)
|
||||
elif self.precision == 2:
|
||||
dt = [self.year,self.month]
|
||||
dt[1] += step
|
||||
while dt[1] > 12:
|
||||
dt[1] -= 12
|
||||
dt[0] += 1
|
||||
while dt[1] < 1:
|
||||
dt[1] += 12
|
||||
dt[0] -= 1
|
||||
return MTime(*dt)
|
||||
elif self.precision == 3:
|
||||
dt = self.dateobject
|
||||
d = datetime.timedelta(days=step)
|
||||
newdate = dt + d
|
||||
return MTime(newdate.year,newdate.month,newdate.day)
|
||||
|
||||
|
||||
|
||||
# a range that is exactly one christian week (starting on sunday)
|
||||
class MTimeWeek(MRangeDescriptor):
|
||||
def __init__(self,year=None,week=None):
|
||||
self.year = year
|
||||
self.week = week
|
||||
|
||||
# assume the first day of the first week of this year is 1/1
|
||||
firstday = date(year,1,1)
|
||||
y,w,d = firstday.chrcalendar()
|
||||
if y == self.year:
|
||||
firstday -= datetime.timedelta(days=(d-1))
|
||||
else:
|
||||
firstday += datetime.timedelta(days=8-d)
|
||||
# now we know the real first day, add the weeks we need
|
||||
firstday = firstday + datetime.timedelta(days=7*(week-1))
|
||||
lastday = firstday + datetime.timedelta(days=6)
|
||||
# turn them into local overwritten date objects
|
||||
self.firstday = date(firstday.year,firstday.month,firstday.day)
|
||||
self.lastday = date(lastday.year,lastday.month,lastday.day)
|
||||
# now check if we're still in the same year
|
||||
y,w,_ = self.firstday.chrcalendar()
|
||||
self.year,self.week = y,w
|
||||
# firstday and lastday are already correct
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return str(self.year) + "/W" + str(self.week)
|
||||
def fromstr(self):
|
||||
return str(self)
|
||||
def tostr(self):
|
||||
return str(self)
|
||||
|
||||
def urikeys(self):
|
||||
return {"in":str(self)}
|
||||
|
||||
def desc(self,prefix=False):
|
||||
if prefix:
|
||||
return "in " + "Week " + str(self.week) + " " + str(self.year)
|
||||
else:
|
||||
return "Week " + str(self.week) + " " + str(self.year)
|
||||
|
||||
def informal_desc(self):
|
||||
now = datetime.datetime.now(tz=datetime.timezone.utc)
|
||||
if now.year == self.year: return "Week " + str(self.week)
|
||||
return self.desc()
|
||||
|
||||
def contextual_desc(self,other):
|
||||
if isinstance(other,MTimeWeek):
|
||||
if other.year == self.year: return "Week " + str(self.week)
|
||||
return self.desc()
|
||||
|
||||
def start(self):
|
||||
return self.first_day()
|
||||
def end(self):
|
||||
return self.last_day()
|
||||
|
||||
def first_day(self):
|
||||
return MTime(self.firstday.year,self.firstday.month,self.firstday.day)
|
||||
def last_day(self):
|
||||
return MTime(self.lastday.year,self.lastday.month,self.lastday.day)
|
||||
|
||||
def first_stamp(self):
|
||||
day = self.firstday
|
||||
return int(datetime.datetime.combine(day,datetime.time(tzinfo=datetime.timezone.utc)).timestamp())
|
||||
def last_stamp(self):
|
||||
day = self.lastday + datetime.timedelta(days=1)
|
||||
return int(datetime.datetime.combine(day,datetime.time(tzinfo=datetime.timezone.utc)).timestamp() - 1)
|
||||
|
||||
def next(self,step=1):
|
||||
if abs(step) == math.inf: return None
|
||||
return MTimeWeek(self.year,self.week + step)
|
||||
|
||||
# a range that is defined by separate start and end
|
||||
class MRange(MRangeDescriptor):
|
||||
|
||||
def __init__(self,since=None,to=None):
|
||||
since,to = time_pad(since,to)
|
||||
self.since = since
|
||||
self.to = to
|
||||
if isinstance(self.since,MRange): self.since = self.since.start()
|
||||
if isinstance(self.to,MRange): self.to = self.to.end()
|
||||
|
||||
def __str__(self):
|
||||
return str(self.since) + " - " + str(self.to)
|
||||
def fromstr(self):
|
||||
return str(self.since)
|
||||
def tostr(self):
|
||||
return str(self.to)
|
||||
|
||||
def unlimited(self):
|
||||
return (self.since is None and self.to is None)
|
||||
|
||||
def urikeys(self):
|
||||
keys = {}
|
||||
if self.since is not None: keys["since"] = str(self.since)
|
||||
if self.to is not None: keys["to"] = str(self.to)
|
||||
return keys
|
||||
|
||||
def desc(self,prefix=False):
|
||||
if self.since is not None and self.to is not None:
|
||||
if prefix:
|
||||
return "from " + self.since.contextual_desc(self.to) + " to " + self.to.desc()
|
||||
else:
|
||||
return self.since.contextual_desc(self.to) + " to " + self.to.desc()
|
||||
if self.since is not None and self.to is None:
|
||||
return "since " + self.since.desc()
|
||||
if self.since is None and self.to is not None:
|
||||
return "until " + self.to.desc()
|
||||
if self.since is None and self.to is None:
|
||||
return ""
|
||||
|
||||
def informal_desc(self):
|
||||
# dis gonna be hard
|
||||
return "Not implemented"
|
||||
|
||||
def start(self):
|
||||
return self.since
|
||||
|
||||
def end(self):
|
||||
return self.to
|
||||
|
||||
def first_day(self):
|
||||
return self.since.first_day()
|
||||
def last_day(self):
|
||||
return self.to.last_day()
|
||||
|
||||
def first_stamp(self):
|
||||
if self.since is None: return FIRST_SCROBBLE
|
||||
else: return self.since.first_stamp()
|
||||
def last_stamp(self):
|
||||
if self.to is None: return int(datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).timestamp())
|
||||
else: return self.to.last_stamp()
|
||||
|
||||
def next(self,step=1):
|
||||
if abs(step) == math.inf: return None
|
||||
# hop from the start element by one until we reach the end element
|
||||
diff = 1
|
||||
nxt = self.since
|
||||
while (nxt != self.to):
|
||||
diff += 1
|
||||
nxt = nxt.next(step=1)
|
||||
|
||||
newstart = self.since.next(step=diff*step)
|
||||
newend = self.to.next(step=diff*step)
|
||||
|
||||
return MRange(newstart,newend)
|
||||
|
||||
|
||||
## test
|
||||
|
||||
w = MTimeWeek(2018,40)
|
||||
d = MTime(2019,4,9)
|
||||
m = MTime(2019,7)
|
||||
y = MTime(2020)
|
||||
|
||||
|
||||
|
||||
def range_desc(r,**kwargs):
|
||||
if r is None: return ""
|
||||
return r.desc(**kwargs)
|
||||
|
||||
def time_str(t):
|
||||
return "/".join(str(tp) for tp in t)
|
||||
obj = time_fix(t)
|
||||
return obj.desc()
|
||||
|
||||
# converts strings and stuff to lists
|
||||
# converts strings and stuff to objects
|
||||
def time_fix(t):
|
||||
|
||||
if t is None: return None
|
||||
if isinstance(t,MRangeDescriptor): return t
|
||||
|
||||
if isinstance(t, str):
|
||||
tod = datetime.datetime.utcnow()
|
||||
@ -45,11 +371,13 @@ def time_fix(t):
|
||||
weekdays = ["sunday","monday","tuesday","wednesday","thursday","friday","saturday"]
|
||||
|
||||
if t.lower() in ["today","day"]:
|
||||
t = [tod.year,tod.month,tod.day]
|
||||
elif t.lower() == "month":
|
||||
t = [tod.year,tod.month]
|
||||
elif t.lower() == "year":
|
||||
t = [tod.year]
|
||||
return today()
|
||||
elif t.lower() in ["month","thismonth"]:
|
||||
return thismonth()
|
||||
elif t.lower() in ["year","thisyear"]:
|
||||
return thisyear()
|
||||
elif t.lower() in ["week","thisweek"]:
|
||||
return thisweek()
|
||||
|
||||
|
||||
elif t.lower() in months:
|
||||
@ -67,192 +395,125 @@ def time_fix(t):
|
||||
#if isinstance(t,tuple): t = list(t)
|
||||
try:
|
||||
t = [int(p) for p in t]
|
||||
return t[:3]
|
||||
return MTime(t[:3])
|
||||
except:
|
||||
pass
|
||||
|
||||
if isinstance(t[1],str) and t[1].startswith("W"):
|
||||
try:
|
||||
year = int(t[0])
|
||||
weeknum = int(t[1][1:])
|
||||
return [t[0],"W",t[1]]
|
||||
return MTimeWeek(year=year,week=weeknum)
|
||||
except:
|
||||
pass
|
||||
raise
|
||||
|
||||
|
||||
|
||||
def get_range_object(since=None,to=None,within=None):
|
||||
|
||||
since,to,within = time_fix(since),time_fix(to),time_fix(within)
|
||||
|
||||
# check if we can simplify
|
||||
if since is not None and to is not None and since == to: within = since
|
||||
# TODO
|
||||
|
||||
if within is not None:
|
||||
return within
|
||||
else:
|
||||
return MRange(since,to)
|
||||
|
||||
|
||||
|
||||
# checks if time is a week
|
||||
def is_week(t):
|
||||
return ((len(t) == 3) and (t[1] == "W"))
|
||||
def week_to_days(t):
|
||||
pass
|
||||
|
||||
# makes times the same precision level
|
||||
def time_pad(f,t,full=False):
|
||||
f,t = time_fix(f), time_fix(t)
|
||||
|
||||
if f is None or t is None: return f,t
|
||||
|
||||
# week handling
|
||||
if isinstance(f,MTimeWeek) and isinstance(t,MTimeWeek):
|
||||
if full: return f.start(),t.end()
|
||||
else: return f,t
|
||||
if not isinstance(f,MTimeWeek) and isinstance(t,MTimeWeek):
|
||||
t = t.end()
|
||||
if isinstance(f,MTimeWeek) and not isinstance(t,MTimeWeek):
|
||||
f = f.start()
|
||||
|
||||
while (f.precision < t.precision) or (full and f.precision < 3):
|
||||
f = f.start()
|
||||
while (f.precision > t.precision) or (full and t.precision < 3):
|
||||
t = t.end()
|
||||
|
||||
return f,t
|
||||
|
||||
|
||||
while (len(f) < len(t)) or (full and len(f) < 3):
|
||||
if len(f) == 1: f.append(1)
|
||||
elif len(f) == 2: f.append(1)
|
||||
while (len(f) > len(t)) or (full and len(t) < 3):
|
||||
if len(t) == 1: t.append(12)
|
||||
elif len(t) == 2: t.append(monthrange(*t)[1])
|
||||
|
||||
return (f,t)
|
||||
|
||||
|
||||
def time_desc(t,short=False):
|
||||
if isinstance(t,int):
|
||||
if short:
|
||||
now = datetime.datetime.now(tz=datetime.timezone.utc)
|
||||
difference = int(now.timestamp() - t)
|
||||
|
||||
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)
|
||||
timeobject = datetime.datetime.utcfromtimestamp(t)
|
||||
if difference < 5: return timeobject.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 timeobject.strftime("%d. %B %Y")
|
||||
else:
|
||||
timeobject = datetime.datetime.utcfromtimestamp(t)
|
||||
return timeobject.strftime("%d. %b %Y %I:%M %p")
|
||||
|
||||
|
||||
### TIMESTAMPS
|
||||
|
||||
def timestamp_desc(t,short=False):
|
||||
|
||||
if short:
|
||||
now = datetime.datetime.now(tz=datetime.timezone.utc)
|
||||
difference = int(now.timestamp() - t)
|
||||
|
||||
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)
|
||||
timeobject = datetime.datetime.utcfromtimestamp(t)
|
||||
if difference < 5: return timeobject.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 timeobject.strftime("%d. %B %Y")
|
||||
else:
|
||||
t = time_fix(t)
|
||||
date = [1970,1,1]
|
||||
date[:len(t)] = t
|
||||
timeobject = datetime.datetime(date[0],date[1],date[2],tzinfo=datetime.timezone.utc)
|
||||
|
||||
nowdate = [1970,1,1]
|
||||
nowobject = datetime.datetime.now(tz=datetime.timezone.utc)
|
||||
nowdate[:len(t)] = [nowobject.year, nowobject.month, nowobject.day][:len(t)]
|
||||
nowobject = datetime.datetime(nowdate[0],nowdate[1],nowdate[2],tzinfo=datetime.timezone.utc)
|
||||
if short:
|
||||
if len(t) == 3:
|
||||
diff = (nowobject - timeobject).days
|
||||
if diff == 0: return "Today"
|
||||
if diff == 1: return "Yesterday"
|
||||
if diff < 7 and diff > 1: return timeobject.strftime("%A")
|
||||
#elif len(t) == 2:
|
||||
|
||||
|
||||
if len(t) == 3: return timeobject.strftime("%d. %B %Y")
|
||||
if len(t) == 2: return timeobject.strftime("%B %Y")
|
||||
if len(t) == 1: return timeobject.strftime("%Y")
|
||||
|
||||
def range_desc(since=None,to=None,within=None,short=False):
|
||||
|
||||
# the 'short' var we pass down to some of the time_desc calls is a different one than the one here
|
||||
# the function-wide one indicates whether we want the 'in' 'from' etc at the start
|
||||
# the other one is if we want exact dates or weekdays etc
|
||||
# but we still hand it down because it makes sense
|
||||
|
||||
|
||||
if within is not None:
|
||||
since = within
|
||||
to = within
|
||||
if since is None:
|
||||
sincestr = ""
|
||||
if to is None:
|
||||
tostr = ""
|
||||
|
||||
if isinstance(since,int) and to is None:
|
||||
sincestr = "since " + time_desc(since)
|
||||
shortsincestr = sincestr
|
||||
elif isinstance(to,int) and since is None:
|
||||
tostr = "up until " + time_desc(to)
|
||||
elif isinstance(since,int) and not isinstance(to,int):
|
||||
sincestr = "from " + time_desc(since)
|
||||
shortsincestr = time_desc(since)
|
||||
tostr = "to the end of " + time_desc(to)
|
||||
elif isinstance(to,int) and not isinstance(since,int):
|
||||
sincestr = "from the start of " + time_desc(since)
|
||||
shortsincestr = time_desc(since)
|
||||
tostr = "to " + time_desc(to)
|
||||
|
||||
# if isinstance(since,int) and isinstance(to,int): result = "from " + time_desc(since) + " to " + time_desc(to)
|
||||
# elif isinstance(since,int): result = "from " + time_desc(since) + " to the end of " + time_desc(to)
|
||||
# elif isinstance(to,int): result = "from the start of " + time_desc(since) + " to " + time_desc(to)
|
||||
else:
|
||||
if since is not None and to is not None:
|
||||
since,to = time_pad(since,to)
|
||||
if since == to:
|
||||
if len(since) == 3:
|
||||
sincestr = "on " + time_desc(since)
|
||||
else:
|
||||
sincestr = "in " + time_desc(since)
|
||||
shortsincestr = time_desc(since,short=True)
|
||||
tostr = ""
|
||||
elif _week(since,to):
|
||||
|
||||
sincestr = "in " + _week(since,to)
|
||||
shortsincestr = _week(since,to)
|
||||
tostr = ""
|
||||
else:
|
||||
fparts = time_desc(since).split(" ")
|
||||
tparts = time_desc(to).split(" ")
|
||||
|
||||
fparts.reverse()
|
||||
tparts.reverse()
|
||||
|
||||
fparts = fparts[len(commonprefix([fparts,tparts])):]
|
||||
|
||||
fparts.reverse()
|
||||
tparts.reverse()
|
||||
|
||||
sincestr = "from " + " ".join(fparts)
|
||||
shortsincestr = " ".join(fparts)
|
||||
tostr = "to " + " ".join(tparts)
|
||||
|
||||
else:
|
||||
if since is not None:
|
||||
sincestr = "since " + time_desc(since)
|
||||
shortsincestr = sincestr
|
||||
if to is not None:
|
||||
tostr = "up until " + time_desc(to)
|
||||
|
||||
if short: return shortsincestr + " " + tostr
|
||||
else: return sincestr + " " + tostr
|
||||
timeobject = datetime.datetime.utcfromtimestamp(t)
|
||||
return timeobject.strftime("%d. %b %Y %I:%M %p")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def time_stamps(since=None,to=None,within=None):
|
||||
|
||||
|
||||
if within is not None:
|
||||
since = within
|
||||
to = within
|
||||
|
||||
|
||||
|
||||
def time_stamps(since=None,to=None,within=None,range=None):
|
||||
|
||||
if (since==None): stamp1 = FIRST_SCROBBLE
|
||||
else:
|
||||
since = time_fix(since)
|
||||
date = [1970,1,1]
|
||||
date[:len(since)] = since
|
||||
stamp1 = int(datetime.datetime(date[0],date[1],date[2],tzinfo=datetime.timezone.utc).timestamp())
|
||||
|
||||
if (to==None): stamp2 = int(datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).timestamp())
|
||||
else:
|
||||
to = time_fix(to)
|
||||
to = _get_next(to)
|
||||
date = [1970,1,1]
|
||||
date[:len(to)] = to
|
||||
stamp2 = int(datetime.datetime(date[0],date[1],date[2],tzinfo=datetime.timezone.utc).timestamp())
|
||||
|
||||
|
||||
return (stamp1,stamp2-1)
|
||||
if range is None: range = get_range_object(since=since,to=to,within=within)
|
||||
return range.first_stamp(),range.last_stamp()
|
||||
#print(range.desc())
|
||||
# if (since==None): stamp1 = FIRST_SCROBBLE
|
||||
# else: stamp1 = range.first_stamp()
|
||||
# if (to==None): stamp2 = int(datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).timestamp())
|
||||
# else: stamp2 = range.last_stamp()
|
||||
# return stamp1,stamp2
|
||||
# if (since==None): stamp1 = FIRST_SCROBBLE
|
||||
# else:
|
||||
# stamp1 = since1
|
||||
# since = time_fix(since)
|
||||
# date = [1970,1,1]
|
||||
# date[:len(since)] = since
|
||||
# stamp1 = int(datetime.datetime(date[0],date[1],date[2],tzinfo=datetime.timezone.utc).timestamp())
|
||||
#
|
||||
# if (to==None): stamp2 = int(datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).timestamp())
|
||||
# else:
|
||||
# to = time_fix(to)
|
||||
# to = _get_next(to)
|
||||
# date = [1970,1,1]
|
||||
# date[:len(to)] = to
|
||||
# stamp2 = int(datetime.datetime(date[0],date[1],date[2],tzinfo=datetime.timezone.utc).timestamp())
|
||||
#
|
||||
#
|
||||
# return (stamp1,stamp2-1)
|
||||
|
||||
|
||||
|
||||
@ -260,118 +521,142 @@ def time_stamps(since=None,to=None,within=None):
|
||||
def delimit_desc(step="month",stepn=1,trail=1):
|
||||
txt = ""
|
||||
if stepn is not 1: txt += _num(stepn) + "-"
|
||||
txt += {"year":"Yearly","month":"Monthly","day":"Daily"}[step.lower()]
|
||||
txt += {"year":"Yearly","month":"Monthly","week":"Weekly","day":"Daily"}[step.lower()]
|
||||
#if trail is not 1: txt += " " + _num(trail) + "-Trailing"
|
||||
if trail is not 1: txt += " Trailing" #we don't need all the info in the title
|
||||
if trail is math.inf: txt += " Cumulative"
|
||||
elif trail is not 1: txt += " Trailing" #we don't need all the info in the title
|
||||
|
||||
return txt
|
||||
|
||||
|
||||
def _week(since,to):
|
||||
if len(since) != 3 or len(to) != 3: return False
|
||||
dt_since, dt_to = datetime.datetime(*since,tzinfo=datetime.timezone.utc), datetime.datetime(*to,tzinfo=datetime.timezone.utc)
|
||||
if (dt_to - dt_since).days != 6: return False
|
||||
if dt_since.weekday() != 6: return False
|
||||
|
||||
c = dt_to.isocalendar()[:2]
|
||||
return str("Week " + str(c[1]) + " " + str(c[0]))
|
||||
|
||||
def _num(i):
|
||||
names = ["Zero","One","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Eleven","Twelve"]
|
||||
if i < len(names): return names[i]
|
||||
else: return str(i)
|
||||
|
||||
|
||||
def day_from_timestamp(stamp):
|
||||
dt = datetime.datetime.utcfromtimestamp(stamp)
|
||||
return MTime(dt.year,dt.month,dt.day)
|
||||
def month_from_timestamp(stamp):
|
||||
dt = datetime.datetime.utcfromtimestamp(stamp)
|
||||
return MTime(dt.year,dt.month)
|
||||
def year_from_timestamp(stamp):
|
||||
dt = datetime.datetime.utcfromtimestamp(stamp)
|
||||
return MTime(dt.year)
|
||||
def week_from_timestamp(stamp):
|
||||
dt = datetime.datetime.utcfromtimestamp(stamp)
|
||||
d = date(dt.year,dt.month,dt.day)
|
||||
y,w,_ = d.chrcalendar()
|
||||
return MTimeWeek(y,w)
|
||||
|
||||
def from_timestamp(stamp,unit):
|
||||
if unit == "day": return day_from_timestamp(stamp)
|
||||
if unit == "week": return week_from_timestamp(stamp)
|
||||
if unit == "month": return month_from_timestamp(stamp)
|
||||
if unit == "year": return year_from_timestamp(stamp)
|
||||
|
||||
|
||||
# since, to and within can accept old notations or objects. timerange can only be a new object.
|
||||
def ranges(since=None,to=None,within=None,timerange=None,step="month",stepn=1,trail=1,max_=None):
|
||||
|
||||
(firstincluded,lastincluded) = time_stamps(since=since,to=to,within=within,range=timerange)
|
||||
|
||||
def ranges(since=None,to=None,within=None,step="month",stepn=1,trail=1,max_=None):
|
||||
|
||||
(firstincluded,lastincluded) = time_stamps(since=since,to=to,within=within)
|
||||
|
||||
d_start = _get_start_of(firstincluded,step)
|
||||
d_end = _get_start_of(lastincluded,step)
|
||||
d_start = _get_next(d_start,step,stepn) # first range should end right after the first active scrobbling week / month / whatever relevant step
|
||||
d_start = _get_next(d_start,step,stepn * trail * -1) # go one range back to begin
|
||||
|
||||
d_start = from_timestamp(firstincluded,step)
|
||||
d_start = d_start.next(stepn-1) #last part of first included range
|
||||
|
||||
i = 0
|
||||
d_current = d_start
|
||||
while not _is_past(d_current,d_end) and (max_ is None or i < max_):
|
||||
d_current_end = _get_end(d_current,step,stepn * trail)
|
||||
yield (d_current,d_current_end)
|
||||
d_current = _get_next(d_current,step,stepn)
|
||||
current_end = d_start
|
||||
while current_end.first_stamp() <= lastincluded and (max_ is None or i < max_):
|
||||
current_start = current_end.next((stepn*trail-1)*-1)
|
||||
if current_start == current_end:
|
||||
yield current_start
|
||||
else:
|
||||
yield MRange(current_start,current_end)
|
||||
current_end = current_end.next(stepn)
|
||||
i += 1
|
||||
|
||||
|
||||
|
||||
def _get_start_of(timestamp,unit):
|
||||
date = datetime.datetime.utcfromtimestamp(timestamp)
|
||||
if unit == "year":
|
||||
#return [date.year,1,1]
|
||||
return [date.year]
|
||||
elif unit == "month":
|
||||
#return [date.year,date.month,1]
|
||||
return [date.year,date.month]
|
||||
elif unit == "day":
|
||||
return [date.year,date.month,date.day]
|
||||
elif unit == "week":
|
||||
change = (date.weekday() + 1) % 7
|
||||
d = datetime.timedelta(days=change)
|
||||
newdate = date - d
|
||||
return [newdate.year,newdate.month,newdate.day]
|
||||
|
||||
def _get_next(time,unit="auto",step=1):
|
||||
result = time[:]
|
||||
if unit == "auto":
|
||||
# see how long the list is, increment by the last specified unit
|
||||
unit = [None,"year","month","day"][len(time)]
|
||||
#while len(time) < 3:
|
||||
# time.append(1)
|
||||
|
||||
if unit == "year":
|
||||
#return [time[0] + step,time[1],time[2]]
|
||||
result[0] += step
|
||||
return result
|
||||
elif unit == "month":
|
||||
#result = [time[0],time[1] + step,time[2]]
|
||||
result[1] += step
|
||||
while result[1] > 12:
|
||||
result[1] -= 12
|
||||
result[0] += 1
|
||||
while result[1] < 1:
|
||||
result[1] += 12
|
||||
result[0] -= 1
|
||||
return result
|
||||
elif unit == "day":
|
||||
dt = datetime.datetime(time[0],time[1],time[2])
|
||||
d = datetime.timedelta(days=step)
|
||||
newdate = dt + d
|
||||
return [newdate.year,newdate.month,newdate.day]
|
||||
#eugh
|
||||
elif unit == "week":
|
||||
return _get_next(time,"day",step * 7)
|
||||
def today():
|
||||
tod = date.today()
|
||||
return MTime(tod.year,tod.month,tod.day)
|
||||
def thisweek():
|
||||
tod = date.today()
|
||||
y,w,_ = tod.chrcalendar()
|
||||
return MTimeWeek(y,w)
|
||||
def thismonth():
|
||||
tod = date.today()
|
||||
return MTime(tod.year,tod.month)
|
||||
def thisyear():
|
||||
tod = date.today()
|
||||
return MTime(tod.year)
|
||||
|
||||
#def _get_start_of(timestamp,unit):
|
||||
# date = datetime.datetime.utcfromtimestamp(timestamp)
|
||||
# if unit == "year":
|
||||
# #return [date.year,1,1]
|
||||
# return [date.year]
|
||||
# elif unit == "month":
|
||||
# #return [date.year,date.month,1]
|
||||
# return [date.year,date.month]
|
||||
# elif unit == "day":
|
||||
# return [date.year,date.month,date.day]
|
||||
# elif unit == "week":
|
||||
# change = (date.weekday() + 1) % 7
|
||||
# d = datetime.timedelta(days=change)
|
||||
# newdate = date - d
|
||||
# return [newdate.year,newdate.month,newdate.day]
|
||||
#
|
||||
#def _get_next(time,unit="auto",step=1):
|
||||
# result = time[:]
|
||||
# if unit == "auto":
|
||||
# if is_week(time): unit = "week"
|
||||
# # see how long the list is, increment by the last specified unit
|
||||
# else: unit = [None,"year","month","day"][len(time)]
|
||||
# #while len(time) < 3:
|
||||
# # time.append(1)
|
||||
#
|
||||
# if unit == "year":
|
||||
# #return [time[0] + step,time[1],time[2]]
|
||||
# result[0] += step
|
||||
# return result
|
||||
# elif unit == "month":
|
||||
# #result = [time[0],time[1] + step,time[2]]
|
||||
# result[1] += step
|
||||
# while result[1] > 12:
|
||||
# result[1] -= 12
|
||||
# result[0] += 1
|
||||
# while result[1] < 1:
|
||||
# result[1] += 12
|
||||
# result[0] -= 1
|
||||
# return result
|
||||
# elif unit == "day":
|
||||
# dt = datetime.datetime(time[0],time[1],time[2])
|
||||
# d = datetime.timedelta(days=step)
|
||||
# newdate = dt + d
|
||||
# return [newdate.year,newdate.month,newdate.day]
|
||||
# #eugh
|
||||
# elif unit == "week":
|
||||
# return _get_next(time,"day",step * 7)
|
||||
#
|
||||
# like _get_next(), but gets the last INCLUDED day / month whatever
|
||||
def _get_end(time,unit="auto",step=1):
|
||||
if step == 1:
|
||||
if unit == "auto": return time[:]
|
||||
if unit == "year" and len(time) == 1: return time[:]
|
||||
if unit == "month" and len(time) == 2: return time[:]
|
||||
if unit == "day" and len(time) == 3: return time[:]
|
||||
exc = _get_next(time,unit,step)
|
||||
inc = _get_next(exc,"auto",-1)
|
||||
return inc
|
||||
#def _get_end(time,unit="auto",step=1):
|
||||
# if step == 1:
|
||||
# if unit == "auto": return time[:]
|
||||
# if unit == "year" and len(time) == 1: return time[:]
|
||||
# if unit == "month" and len(time) == 2: return time[:]
|
||||
# if unit == "day" and len(time) == 3: return time[:]
|
||||
# exc = _get_next(time,unit,step)
|
||||
# inc = _get_next(exc,"auto",-1)
|
||||
# return inc
|
||||
#
|
||||
|
||||
|
||||
|
||||
def _is_past(date,limit):
|
||||
date_, limit_ = date[:], limit[:]
|
||||
while len(date_) != 3: date_.append(1)
|
||||
while len(limit_) != 3: limit_.append(1)
|
||||
if not date_[0] == limit_[0]:
|
||||
return date_[0] > limit_[0]
|
||||
if not date_[1] == limit_[1]:
|
||||
return date_[1] > limit_[1]
|
||||
return (date_[2] > limit_[2])
|
||||
#def _is_past(date,limit):
|
||||
# date_, limit_ = date[:], limit[:]
|
||||
# while len(date_) != 3: date_.append(1)
|
||||
# while len(limit_) != 3: limit_.append(1)
|
||||
# if not date_[0] == limit_[0]:
|
||||
# return date_[0] > limit_[0]
|
||||
# if not date_[1] == limit_[1]:
|
||||
# return date_[1] > limit_[1]
|
||||
# return (date_[2] > limit_[2])
|
||||
##
|
||||
|
@ -1,7 +1,7 @@
|
||||
import urllib
|
||||
from bottle import FormsDict
|
||||
from malojatime import time_fix, time_str
|
||||
|
||||
from malojatime import time_fix, time_str, get_range_object
|
||||
import math
|
||||
|
||||
# necessary because urllib.parse.urlencode doesnt handle multidicts
|
||||
def compose_querystring(*dicts,exclude=[]):
|
||||
@ -39,7 +39,7 @@ def remove_identical(*dicts):
|
||||
return new
|
||||
|
||||
|
||||
|
||||
# this also sets defaults!
|
||||
def uri_to_internal(keys,forceTrack=False,forceArtist=False):
|
||||
|
||||
# output:
|
||||
@ -59,41 +59,54 @@ def uri_to_internal(keys,forceTrack=False,forceArtist=False):
|
||||
|
||||
# 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"]
|
||||
|
||||
# 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"]
|
||||
since,to,within = None,None,None
|
||||
if "since" in keys: since = keys.get("since")
|
||||
elif "from" in keys: since = keys.get("from")
|
||||
elif "start" in keys: since = keys.get("start")
|
||||
if "to" in keys: to = keys.get("to")
|
||||
elif "until" in keys: to = keys.get("until")
|
||||
elif "end" in keys: to = keys.get("end")
|
||||
if "in" in keys: within = keys.get("in")
|
||||
elif "within" in keys: within = keys.get("within")
|
||||
elif "during" in keys: within = keys.get("during")
|
||||
resultkeys2["timerange"] = get_range_object(since=since,to=to,within=within)
|
||||
|
||||
#3
|
||||
resultkeys3 = {}
|
||||
resultkeys3 = {"step":"month","stepn":1,"trail":1}
|
||||
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"])
|
||||
if "cumulative" in keys: resultkeys3["trail"] = math.inf
|
||||
|
||||
|
||||
|
||||
#4
|
||||
resultkeys4 = {}
|
||||
resultkeys4 = {"max_":300}
|
||||
if "max" in keys: resultkeys4["max_"] = int(keys["max"])
|
||||
|
||||
|
||||
return resultkeys1, resultkeys2, resultkeys3, resultkeys4
|
||||
|
||||
def internal_to_uri(keys):
|
||||
@ -109,12 +122,16 @@ def internal_to_uri(keys):
|
||||
urikeys.append("title",keys["track"]["title"])
|
||||
|
||||
#time
|
||||
if "within" in keys:
|
||||
if "timerange" in keys:
|
||||
keydict = keys["timerange"].urikeys()
|
||||
for k in keydict:
|
||||
urikeys.append(k,keydict[k])
|
||||
elif "within" in keys:
|
||||
urikeys.append("in",time_str(keys["within"]))
|
||||
else:
|
||||
if "since" in keys:
|
||||
if "since" in keys and keys["since"] is not None:
|
||||
urikeys.append("since",time_str(keys["since"]))
|
||||
if "to" in keys:
|
||||
if "to" in keys and keys["to"] is not None:
|
||||
urikeys.append("to",time_str(keys["to"]))
|
||||
|
||||
# delimit
|
||||
@ -123,7 +140,10 @@ def internal_to_uri(keys):
|
||||
if "stepn" in keys:
|
||||
urikeys.append("stepn",str(keys["stepn"]))
|
||||
if "trail" in keys:
|
||||
urikeys.append("trail",str(keys["trail"]))
|
||||
if keys["trail"] == math.inf:
|
||||
urikeys.append("cumulative","yes")
|
||||
else:
|
||||
urikeys.append("trail",str(keys["trail"]))
|
||||
|
||||
# stuff
|
||||
if "max_" in keys:
|
||||
|
@ -10,7 +10,7 @@ def instructions(keys):
|
||||
|
||||
_, timekeys, _, amountkeys = uri_to_internal(keys)
|
||||
|
||||
limitstring = range_desc(**timekeys)
|
||||
limitstring = timekeys["timerange"].desc(prefix=True)
|
||||
|
||||
html_filterselector = module_filterselection(keys)
|
||||
|
||||
|
@ -26,7 +26,7 @@ def instructions(keys):
|
||||
else:
|
||||
imgurl = ""
|
||||
|
||||
limitstring += " " + range_desc(**timekeys)
|
||||
limitstring += " " + timekeys["timerange"].desc(prefix=True)
|
||||
|
||||
pushresources = [{"file":imgurl,"type":"image"}] if imgurl.startswith("/") else []
|
||||
|
||||
|
@ -24,7 +24,7 @@ def instructions(keys):
|
||||
#limitkey["artist"], limitkey["associated"] = keys.get("artist"), (keys.get("associated")!=None)
|
||||
limitstring += "of " + artistLink(filterkeys.get("artist"))
|
||||
|
||||
limitstring += " " + range_desc(**timekeys)
|
||||
limitstring += " " + timekeys["timerange"].desc(prefix=True)
|
||||
|
||||
delimitstring = delimit_desc(**delimitkeys)
|
||||
|
||||
|
@ -29,7 +29,7 @@ def instructions(keys):
|
||||
if moreartists != []:
|
||||
limitstring += " <span class='extra'>including " + artistLinks(moreartists) + "</span>"
|
||||
|
||||
limitstring += " " + range_desc(**timekeys)
|
||||
limitstring += " " + range_desc(timekeys["timerange"],prefix=True)
|
||||
|
||||
delimitstring = delimit_desc(**delimitkeys)
|
||||
|
||||
|
@ -26,7 +26,7 @@ def instructions(keys):
|
||||
if moreartists != []:
|
||||
limitstring += " <span class='extra'>including " + artistLinks(moreartists) + "</span>"
|
||||
|
||||
limitstring += " " + range_desc(**timekeys)
|
||||
limitstring += " " + timekeys["timerange"].desc(prefix=True)
|
||||
|
||||
html_filterselector = module_filterselection(keys)
|
||||
|
||||
|
@ -77,6 +77,7 @@
|
||||
<div class="sidelist">
|
||||
<h1><a href="/scrobbles?max=100">Last Scrobbles</a></h1>
|
||||
<span class="stats">Today</span> KEY_SCROBBLE_NUM_TODAY
|
||||
<span class="stats">This Week</span> KEY_SCROBBLE_NUM_WEEK
|
||||
<span class="stats">This month</span> KEY_SCROBBLE_NUM_MONTH
|
||||
<span class="stats">This year</span> KEY_SCROBBLE_NUM_YEAR
|
||||
<span class="stats">All Time</span> KEY_SCROBBLE_NUM_TOTAL
|
||||
|
@ -14,33 +14,29 @@ def instructions(keys):
|
||||
js_command += "showRange('toptracks','" + get_settings("DEFAULT_RANGE_CHARTS_TRACKS") + "');"
|
||||
js_command += "showRange('pulse','" + get_settings("DEFAULT_RANGE_PULSE") + "');"
|
||||
|
||||
# get start of week
|
||||
tod = datetime.utcnow()
|
||||
change = (tod.weekday() + 1) % 7
|
||||
d = timedelta(days=change)
|
||||
newdate = tod - d
|
||||
weekstart = [newdate.year,newdate.month,newdate.day]
|
||||
|
||||
#clock()
|
||||
clock()
|
||||
|
||||
from malojatime import today,thisweek,thismonth,thisyear
|
||||
|
||||
# artists
|
||||
|
||||
topartists_total = module_artistcharts_tiles()
|
||||
topartists_year = module_artistcharts_tiles(since="year")
|
||||
topartists_month = module_artistcharts_tiles(since="month")
|
||||
topartists_week = module_artistcharts_tiles(since=weekstart)
|
||||
topartists_year = module_artistcharts_tiles(timerange=thisyear())
|
||||
topartists_month = module_artistcharts_tiles(timerange=thismonth())
|
||||
topartists_week = module_artistcharts_tiles(timerange=thisweek())
|
||||
|
||||
#clockp("Artists")
|
||||
clockp("Artists")
|
||||
|
||||
# tracks
|
||||
|
||||
toptracks_total = module_trackcharts_tiles()
|
||||
toptracks_year = module_trackcharts_tiles(since="year")
|
||||
toptracks_month = module_trackcharts_tiles(since="month")
|
||||
toptracks_week = module_trackcharts_tiles(since=weekstart)
|
||||
toptracks_year = module_trackcharts_tiles(timerange=thisyear())
|
||||
toptracks_month = module_trackcharts_tiles(timerange=thismonth())
|
||||
toptracks_week = module_trackcharts_tiles(timerange=thisweek())
|
||||
|
||||
|
||||
#clockp("Tracks")
|
||||
clockp("Tracks")
|
||||
|
||||
|
||||
|
||||
@ -48,63 +44,50 @@ def instructions(keys):
|
||||
# scrobbles
|
||||
html_scrobbles, _, _ = module_scrobblelist(max_=15,shortTimeDesc=True,pictures=True,earlystop=True)
|
||||
|
||||
#clockp("Scrobbles")
|
||||
clockp("Scrobbles")
|
||||
|
||||
# stats
|
||||
|
||||
#(amount_day,amount_month,amount_year,amount_total) = database.get_scrobbles_num_multiple(("today","month","year",None))
|
||||
#amount_month += amount_day
|
||||
#amount_year += amount_month
|
||||
#amount_total += amount_year
|
||||
amount_day = database.get_scrobbles_num(timerange=today())
|
||||
scrobbles_today = "<a href='/scrobbles?in=today'>" + str(amount_day) + "</a>"
|
||||
|
||||
amount_day = database.get_scrobbles_num(since="today")
|
||||
scrobbles_today = "<a href='/scrobbles?since=today'>" + str(amount_day) + "</a>"
|
||||
amount_week = database.get_scrobbles_num(timerange=thisweek())
|
||||
scrobbles_week = "<a href='/scrobbles?in=week'>" + str(amount_week) + "</a>"
|
||||
|
||||
amount_month = database.get_scrobbles_num(since="month")
|
||||
scrobbles_month = "<a href='/scrobbles?since=month'>" + str(amount_month) + "</a>"
|
||||
amount_month = database.get_scrobbles_num(timerange=thismonth())
|
||||
scrobbles_month = "<a href='/scrobbles?in=month'>" + str(amount_month) + "</a>"
|
||||
|
||||
amount_year = database.get_scrobbles_num(since="year")
|
||||
scrobbles_year = "<a href='/scrobbles?since=year'>" + str(amount_year) + "</a>"
|
||||
amount_year = database.get_scrobbles_num(timerange=thisyear())
|
||||
scrobbles_year = "<a href='/scrobbles?in=year'>" + str(amount_year) + "</a>"
|
||||
|
||||
amount_total = database.get_scrobbles_num()
|
||||
scrobbles_total = "<a href='/scrobbles'>" + str(amount_total) + "</a>"
|
||||
|
||||
#clockp("Amounts")
|
||||
clockp("Amounts")
|
||||
|
||||
# pulse
|
||||
dt = datetime.utcnow()
|
||||
first_month = [dt.year-1,dt.month+1]
|
||||
dt_firstweek = dt - timedelta(11*7) - timedelta((tod.weekday() + 1) % 7)
|
||||
first_week = [dt_firstweek.year,dt_firstweek.month,dt_firstweek.day]
|
||||
dt_firstday = dt - timedelta(6)
|
||||
first_day = [dt_firstday.year,dt_firstday.month,dt_firstday.day]
|
||||
first_year = [dt.year - 9]
|
||||
if first_month[1] > 12: first_month = [first_month[0]+1,first_month[1]-12]
|
||||
|
||||
html_pulse_days = module_pulse(max_=7,since=first_day,step="day",trail=1)
|
||||
html_pulse_weeks = module_pulse(max_=12,since=first_week,step="week",trail=1)
|
||||
html_pulse_months = module_pulse(max_=12,since=first_month,step="month",trail=1)
|
||||
html_pulse_years = module_pulse(max_=10,since=first_year,step="year",trail=1)
|
||||
|
||||
html_pulse_days = module_pulse(max_=7,since=today().next(-6),step="day",trail=1)
|
||||
html_pulse_weeks = module_pulse(max_=12,since=thisweek().next(-11),step="week",trail=1)
|
||||
html_pulse_months = module_pulse(max_=12,since=thismonth().next(-11),step="month",trail=1)
|
||||
html_pulse_years = module_pulse(max_=10,since=thisyear().next(-9),step="year",trail=1)
|
||||
|
||||
|
||||
#html_pulse_week = module_pulse(max_=7,since=weekstart,step="day",trail=1)
|
||||
#html_pulse_month = module_pulse(max_=30,since=[dt.year,dt.month],step="day",trail=1)
|
||||
#html_pulse_year = module_pulse(max_=12,since=[dt.year],step="month",trail=1)
|
||||
|
||||
#clockp("Pulse")
|
||||
clockp("Pulse")
|
||||
|
||||
#pushresources = [{"file":img,"type":"image"} for img in artistimages + trackimages] #can't push scrobble images as we don't get them from the module function, need to think about that
|
||||
pushresources = []
|
||||
|
||||
replace = {
|
||||
# "KEY_ARTISTIMAGE":artistimages,"KEY_ARTISTNAME":artisttitles,"KEY_ARTISTLINK":artistlinks,"KEY_POSITION_ARTIST":posrange,
|
||||
# "KEY_TRACKIMAGE":trackimages,"KEY_TRACKNAME":tracktitles,"KEY_TRACKLINK":tracklinks,"KEY_POSITION_TRACK":posrange,
|
||||
# "KEY_SCROBBLE_TIME":scrobbletimes,"KEY_SCROBBLE_ARTISTS":scrobbleartists,"KEY_SCROBBLE_TITLE":scrobbletracklinks,"KEY_SCROBBLE_IMAGE":scrobbleimages,
|
||||
# "KEY_PULSE_TERM":pulse_rangedescs,"KEY_PULSE_AMOUNT":pulse_amounts,"KEY_PULSE_BAR":pulse_bars
|
||||
"KEY_TOPARTISTS_TOTAL":topartists_total,"KEY_TOPARTISTS_YEAR":topartists_year,"KEY_TOPARTISTS_MONTH":topartists_month,"KEY_TOPARTISTS_WEEK":topartists_week,
|
||||
"KEY_TOPTRACKS_TOTAL":toptracks_total,"KEY_TOPTRACKS_YEAR":toptracks_year,"KEY_TOPTRACKS_MONTH":toptracks_month,"KEY_TOPTRACKS_WEEK":toptracks_week,
|
||||
"KEY_JS_INIT_RANGES":js_command,
|
||||
"KEY_SCROBBLE_NUM_TODAY":scrobbles_today,"KEY_SCROBBLE_NUM_MONTH":scrobbles_month,"KEY_SCROBBLE_NUM_YEAR":scrobbles_year,"KEY_SCROBBLE_NUM_TOTAL":scrobbles_total,
|
||||
"KEY_SCROBBLE_NUM_TODAY":scrobbles_today,"KEY_SCROBBLE_NUM_WEEK":scrobbles_week,"KEY_SCROBBLE_NUM_MONTH":scrobbles_month,"KEY_SCROBBLE_NUM_YEAR":scrobbles_year,"KEY_SCROBBLE_NUM_TOTAL":scrobbles_total,
|
||||
"KEY_SCROBBLES":html_scrobbles,
|
||||
"KEY_PULSE_MONTHS":html_pulse_months,"KEY_PULSE_YEARS":html_pulse_years,"KEY_PULSE_DAYS":html_pulse_days,"KEY_PULSE_WEEKS":html_pulse_weeks,
|
||||
#"KEY_PULSE_YEAR":html_pulse_year,"KEY_PULSE_MONTH":html_pulse_month,"KEY_PULSE_WEEK":html_pulse_week
|
||||
|
@ -26,7 +26,7 @@ def instructions(keys):
|
||||
else:
|
||||
imgurl = ""
|
||||
|
||||
limitstring += " " + range_desc(**timekeys)
|
||||
limitstring += " " + timekeys["timerange"].desc(prefix=True)
|
||||
|
||||
pushresources = [{"file":imgurl,"type":"image"}] if imgurl.startswith("/") else []
|
||||
|
||||
|
@ -26,7 +26,7 @@ def instructions(keys):
|
||||
else:
|
||||
imgurl = ""
|
||||
|
||||
limitstring += " " + range_desc(**timekeys)
|
||||
limitstring += " " + timekeys["timerange"].desc(prefix=True)
|
||||
|
||||
pushresources = [{"file":imgurl,"type":"image"}] if imgurl.startswith("/") else []
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user