diff --git a/maloja/htmlmodules.py b/maloja/htmlmodules.py
deleted file mode 100644
index bf108ae..0000000
--- a/maloja/htmlmodules.py
+++ /dev/null
@@ -1,677 +0,0 @@
-from .htmlgenerators import *
-from . import database
-from .utilities import getArtistImage, getTrackImage
-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):
-# from utilities import getArtistsInfo, getTracksInfo
-# if tracks:
-# for element in getTracksInfo(ls):
-# result.append(element.get("image"))
-# else:
-# for element in getArtistsInfo(ls):
-# result.append(element.get("image"))
-
-
-#max_ indicates that no pagination should occur (because this is not the primary module)
-def module_scrobblelist(page=0,perpage=100,max_=None,pictures=False,shortTimeDesc=False,earlystop=False,**kwargs):
-
- kwargs_filter = pickKeys(kwargs,"artist","track","associated")
- kwargs_time = pickKeys(kwargs,"timerange","since","to","within")
-
- if max_ is not None: perpage,page=max_,0
-
- firstindex = page * perpage
- lastindex = firstindex + perpage
-
- # if earlystop, we don't care about the actual amount and only request as many from the db
- # without, we request everything and filter on site
- maxkey = {"max_":lastindex} if earlystop else {}
- scrobbles = database.get_scrobbles(**kwargs_time,**kwargs_filter,**maxkey)
- if pictures:
- scrobbleswithpictures = [""] * firstindex + scrobbles[firstindex:lastindex]
- #scrobbleimages = [e.get("image") for e in getTracksInfo(scrobbleswithpictures)] #will still work with scrobble objects as they are a technically a subset of track objects
- #scrobbleimages = ["/image?title=" + urllib.parse.quote(t["title"]) + "&" + "&".join(["artist=" + urllib.parse.quote(a) for a in t["artists"]]) for t in scrobbleswithpictures]
- scrobbleimages = [getTrackImage(t["artists"],t["title"],fast=True) for t in scrobbleswithpictures]
-
- pages = math.ceil(len(scrobbles) / perpage)
-
- representative = scrobbles[0] if len(scrobbles) is not 0 else None
-
- # build list
- i = 0
- html = "
"
- if pictures:
- img = scrobbleimages[i]
- else: img = None
- html += entity_column(s,image=img)
- html += ""
-
- i += 1
- if i>=lastindex:
- break
-
-
- html += "
"
-
- if max_ is None: html += module_paginate(page=page,pages=pages,perpage=perpage,**kwargs)
-
- return (html,len(scrobbles),representative)
-
-
-def module_pulse(page=0,perpage=100,max_=None,**kwargs):
-
- from doreah.timing import clock, clockp
-
- kwargs_filter = pickKeys(kwargs,"artist","track","associated")
- kwargs_time = pickKeys(kwargs,"since","to","within","timerange","step","stepn","trail")
-
- if max_ is not None: perpage,page=max_,0
-
- firstindex = page * perpage
- lastindex = firstindex + perpage
-
-
- ranges = database.get_pulse(**kwargs_time,**kwargs_filter)
-
- pages = math.ceil(len(ranges) / perpage)
-
- ranges = ranges[firstindex:lastindex]
-
- # if time range not explicitly specified, only show from first appearance
-# if "since" not in kwargs:
-# while ranges[0]["scrobbles"] == 0:
-# del ranges[0]
-
- maxbar = max([t["scrobbles"] for t in ranges])
- maxbar = max(maxbar,1)
-
- #build list
- html = "
"
- for t in ranges:
- range = t["range"]
- html += "
"
-
- if max_ is None: html += module_paginate(page=page,pages=pages,perpage=perpage,**kwargs)
-
- return html
-
-
-
-def module_performance(page=0,perpage=100,max_=None,**kwargs):
-
- kwargs_filter = pickKeys(kwargs,"artist","track")
- kwargs_time = pickKeys(kwargs,"since","to","within","timerange","step","stepn","trail")
-
- if max_ is not None: perpage,page=max_,0
-
- firstindex = page * perpage
- lastindex = firstindex + perpage
-
- ranges = database.get_performance(**kwargs_time,**kwargs_filter)
-
- pages = math.ceil(len(ranges) / perpage)
-
- ranges = ranges[firstindex:lastindex]
-
- # if time range not explicitly specified, only show from first appearance
-# if "since" not in kwargs:
-# while ranges[0]["scrobbles"] == 0:
-# del ranges[0]
-
-
- minrank = 80
- for t in ranges:
- if t["rank"] is not None and t["rank"]+20 > minrank: minrank = t["rank"]+20
-
- #build list
- html = "
"
- for t in ranges:
- range = t["range"]
- html += "
"
- html += "
" + range.desc() + "
"
- html += "
" + ("#" + str(t["rank"]) if t["rank"] is not None else "No scrobbles") + "
"
- prct = (minrank+1-t["rank"])*100/minrank if t["rank"] is not None else 0
- html += "
"
-
- if max_ is None: html += module_paginate(page=page,pages=pages,perpage=perpage,**kwargs)
-
- return (html, representative)
-
-
-
-def module_toptracks(pictures=True,**kwargs):
-
- kwargs_filter = pickKeys(kwargs,"artist","associated")
- kwargs_time = pickKeys(kwargs,"timerange","since","to","within","step","stepn","trail")
-
- tracks = database.get_top_tracks(**kwargs_filter,**kwargs_time)
-
- if tracks != []:
- maxbar = max(t["scrobbles"] for t in tracks)
-
-
- # track with most #1 positions
- max_appear = 0
- representatives = list(t["track"] for t in tracks if t["track"] is not None)
- for t in representatives:
- max_appear = max(max_appear,representatives.count(t))
- #representatives.sort(key=lambda reftrack:len([t for t in tracks if t["track"] == reftrack["track"] and t["track"] is not None]))
- representatives = [t for t in tracks if representatives.count(t["track"]) == max_appear]
- # of these, track with highest scrobbles in its #1 range
- representatives.sort(key=lambda t: t["scrobbles"])
- representative = representatives[-1]["track"]
- else:
- representative = None
-
-
- i = 0
- html = "
"
- for e in tracks:
-
- #fromstr = "/".join([str(p) for p in e["from"]])
- #tostr = "/".join([str(p) for p in e["to"]])
- range = e["range"]
-
- i += 1
- html += "
"
-
-
- html += "
" + range.desc() + "
"
- if e["track"] is None:
- if pictures:
- html += "
"
- html += "
" + "No scrobbles" + "
"
- #html += "
" + "" + "
"
- html += "
" + "0" + "
"
- html += "
" + "" + "
"
- else:
- if pictures:
- img = getTrackImage(e["track"]["artists"],e["track"]["title"],fast=True)
- else: img = None
- html += entity_column(e["track"],image=img)
- html += "
"
-
- return (html,representative)
-
-def module_topartists(pictures=True,**kwargs):
-
- kwargs_time = pickKeys(kwargs,"timerange","since","to","within","step","stepn","trail")
-
- artists = database.get_top_artists(**kwargs_time)
-
- if artists != []:
- maxbar = max(a["scrobbles"] for a in artists)
-
- # artists with most #1 positions
- max_appear = 0
- representatives = list(a["artist"] for a in artists if a["artist"] is not None)
- for a in representatives:
- max_appear = max(max_appear,representatives.count(a))
- representatives = [a for a in artists if representatives.count(a["artist"]) == max_appear]
- # of these, artist with highest scrobbles in their #1 range
- representatives.sort(key=lambda a: a["scrobbles"])
-
- representative = representatives[-1]["artist"]
- else:
- representative = None
-
-
- i = 0
- html = "
"
- for e in artists:
-
- #fromstr = "/".join([str(p) for p in e["from"]])
- #tostr = "/".join([str(p) for p in e["to"]])
- range = e["range"]
-
- i += 1
- html += "
"
-
-
- html += "
" + range.desc() + "
"
-
- if e["artist"] is None:
- if pictures:
- html += "
"
- html += "
" + "No scrobbles" + "
"
- html += "
" + "0" + "
"
- html += "
" + "" + "
"
- else:
- if pictures:
- img = getArtistImage(e["artist"],fast=True)
- else: img = None
- html += entity_column(e["artist"],image=img)
- html += "
"
-
- return (html,representative)
-
-
-def module_artistcharts_tiles(**kwargs):
-
- kwargs_filter = pickKeys(kwargs,"associated") #not used right now
- 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)
-
- i = 1
-
- bigpart = [0,1,2,6,15]
- smallpart = [0,1,2,4,6,9,12,15]
- #rnk = (0,0) #temporary store so entries with the same scrobble amount get the same rank
-
- html = """
"""
-
- for e in artists:
-
-
- if i in bigpart:
- n = bigpart.index(i)
- html += """
"""
-
- return html
-
-
-
-def module_paginate(page,pages,perpage,**keys):
-
- unchangedkeys = internal_to_uri({**keys,"perpage":perpage})
-
- html = "
"
-
- if page > 1:
- html += "" + "1" + ""
- html += " | "
-
- if page > 2:
- html += " ... | "
-
- if page > 0:
- html += "" + str(page) + ""
- html += " « "
-
- html += "" + str(page+1) + ""
-
- if page < pages-1:
- html += " » "
- html += "" + str(page+2) + ""
-
- if page < pages-3:
- html += " | ... "
-
- if page < pages-2:
- html += " | "
- html += "" + str(pages) + ""
-
-
- html += "
"
-
- return html
-
-
-
-# THIS FUNCTION USES THE ORIGINAL URI KEYS!!!
-def module_filterselection(keys,time=True,delimit=False):
-
- from .malojatime import today, thisweek, thismonth, thisyear, alltime
-
- filterkeys, timekeys, delimitkeys, extrakeys = uri_to_internal(keys)
- # drop keys that are not relevant so they don't clutter the URI
- if not time: timekeys = {}
- if not delimit: delimitkeys = {}
- if "page" in extrakeys: del extrakeys["page"]
- internalkeys = {**filterkeys,**timekeys,**delimitkeys,**extrakeys}
-
- html = ""
-
-
- if time:
-
- # wonky selector for precise date range
-
-# fromdate = start_of_scrobbling()
-# todate = end_of_scrobbling()
-# if keys.get("since") is not None: fromdate = keys.get("since")
-# if keys.get("to") is not None: todate = keys.get("to")
-# if keys.get("in") is not None: fromdate, todate = keys.get("in"), keys.get("in")
-# fromdate = time_fix(fromdate)
-# todate = time_fix(todate)
-# fromdate, todate = time_pad(fromdate,todate,full=True)
-# fromdate = [str(e) if e>9 else "0" + str(e) for e in fromdate]
-# todate = [str(e) if e>9 else "0" + str(e) for e in todate]
-#
-# html += "
"
-# html += "from "
-# html += "to "
-# html += "
"
-
- # relative to current range
- html += "
"
-
- thisrange = timekeys.get("timerange")
- prevrange = thisrange.next(-1)
- nextrange = thisrange.next(1)
-
- if prevrange is not None:
- link = compose_querystring(internal_to_uri({**internalkeys,"timerange":prevrange}))
- html += "" + prevrange.desc() + ""
- html += " « "
- if prevrange is not None or nextrange is not None:
- html += "" + thisrange.desc() + ""
- if nextrange is not None:
- html += " » "
- link = compose_querystring(internal_to_uri({**internalkeys,"timerange":nextrange}))
- html += "" + nextrange.desc() + ""
-
- html += "