diff --git a/README.md b/README.md index a7c05f0..1ca7432 100644 --- a/README.md +++ b/README.md @@ -28,15 +28,15 @@ The software works fairly well and has a few web views, but there is only one sc ## How to install -I wouldn't recommend it yet. But if you want to test Maloja, it's fairly easy: +Installing Maloja is fairly easy on a Linux machine. Don't ask me how to do it on Windows, I have no clue. 1) Install the requirements: * [bottle.py](https://github.com/bottlepy/bottle) * [waitress](https://github.com/Pylons/waitress) +2) Put the Maloja folder anywhere and start server.py. -2) Put it anywhere and start server.py 3) (Recommended) Put your server behind a reverse proxy for SSL encryption. Configure that proxy to rewrite /db/ requests to the database port. In nginx this would look as follows: location / { @@ -47,5 +47,7 @@ I wouldn't recommend it yet. But if you want to test Maloja, it's fairly easy: rewrite ^/db(.*)$ $1 break; proxy_pass http://yoururl:42011; } - -If you would like to import all your previous last.fm scrobbles, use [benfoxall's website](https://benjaminbenben.com/lastfm-to-csv/) ([GitHub page](https://github.com/benfoxall/lastfm-to-csv)). Use the python script lastfmconverter.py with two arguments - the downloaded csv file and your new tsv file - to convert your data. Place the tsv file in scrobbles/ and the server will recognize it on startup. + +4) In order to scrobble your music from Plex Web, install the included Chrome extension. Make sure to generate a random key and enter that key in the extension as well as the file autenticated_machines.tsv in the clients folder. + +5) If you would like to import all your previous last.fm scrobbles, use [benfoxall's website](https://benjaminbenben.com/lastfm-to-csv/) ([GitHub page](https://github.com/benfoxall/lastfm-to-csv)). Use the python script lastfmconverter.py with two arguments - the downloaded csv file and your new tsv file - to convert your data. Place the tsv file in scrobbles/ and the server will recognize it on startup. diff --git a/database.py b/database.py index d3eb14a..58d2074 100644 --- a/database.py +++ b/database.py @@ -141,7 +141,7 @@ def test_server(): def get_scrobbles(): keys = FormsDict.decode(request.query) - r = db_query(artists=keys.getall("artist"),title=keys.get("title"),since=keys.get("since"),to=keys.get("to"),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() if keys.get("max") is not None: @@ -153,7 +153,7 @@ def get_scrobbles(): def get_scrobbles(): keys = FormsDict.decode(request.query) - r = db_query(artists=keys.getall("artist"),title=keys.get("title"),since=keys.get("since"),to=keys.get("to"),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() return {"amount":len(r)} @@ -189,30 +189,34 @@ def get_amounts(): 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)} + return {"list":db_aggregate(by="ARTIST",since=since,to=to,within=within)} @dbserver.route("/charts/tracks") def get_charts_tracks(): keys = FormsDict.decode(request.query) since = keys.get("since") to = keys.get("to") + within=request.query.get("in") artist = keys.get("artist") - return {"list":db_aggregate(by="TRACK",since=since,to=to,artist=artist)} + return {"list":db_aggregate(by="TRACK",since=since,to=to,within=within,artist=artist)} @dbserver.route("/charts") def get_charts(): since = request.query.get("since") to = request.query.get("to") + within=request.query.get("in") - return {"number":db_aggregate(since=since,to=to)} + return {"number":db_aggregate(since=since,to=to,within=within)} @dbserver.route("/pulse") def get_pulse(): since = request.query.get("since") to = request.query.get("to") - (ts_start,ts_end) = getTimestamps(since,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)) @@ -244,7 +248,8 @@ def get_pulse(): def get_top_artists(): since = request.query.get("since") to = request.query.get("to") - (ts_start,ts_end) = getTimestamps(since,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)) @@ -278,7 +283,8 @@ def get_top_artists(): def get_top_tracks(): since = request.query.get("since") to = request.query.get("to") - (ts_start,ts_end) = getTimestamps(since,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)) @@ -323,7 +329,13 @@ def getStartOf(timestamp,unit): newdate = date - d return [newdate.year,newdate.month,newdate.day] -def getNext(time,unit,step=1): +def getNext(time,unit="auto",step=1): + 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]] elif unit == "month": @@ -653,8 +665,8 @@ def sync(): # Queries the database -def db_query(artists=None,title=None,track=None,since=None,to=None,associated=False): - (since, to) = getTimestamps(since,to) +def db_query(artists=None,title=None,track=None,since=None,to=None,within=None,associated=False): + (since, to) = getTimestamps(since,to,within) # 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 @@ -686,8 +698,8 @@ def db_query(artists=None,title=None,track=None,since=None,to=None,associated=Fa # Queries that... well... aggregate -def db_aggregate(by=None,since=None,to=None,artist=None): - (since, to) = getTimestamps(since,to) +def db_aggregate(by=None,since=None,to=None,withinin=None,artist=None): + (since, to) = getTimestamps(since,to,within) if isinstance(artist, str): artist = ARTISTS.index(artist) @@ -746,9 +758,14 @@ def db_search(query,type=None): #### -# Takes user inputs like YYYY/MM and returns the timestamps. Returns timestamp if timestamp was already given. -def getTimestamps(f,t): - #(f,t) = inp +# 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): + + if i is not None: + f = i + t = i + if isinstance(f, str) and f.lower() == "today": tod = datetime.datetime.utcnow() f = [tod.year,tod.month,tod.day] @@ -782,15 +799,18 @@ def getTimestamps(f,t): # this step is done if either the input is a list or the first step was done (which creates a list) if isinstance(f, list): - date = [1970,1,1,0,0] - date[:len(f)] = f - f = int(datetime.datetime(date[0],date[1],date[2],date[3],date[4],tzinfo=datetime.timezone.utc).timestamp()) - + #date = [1970,1,1,0,0] + #date[:len(f)] = f + while len(f) < 3: f.append(1) # padding month and day + #f = int(datetime.datetime(date[0],date[1],date[2],date[3],date[4],tzinfo=datetime.timezone.utc).timestamp()) + f = int(datetime.datetime(f[0],f[1],f[2],tzinfo=datetime.timezone.utc).timestamp()) + if isinstance(t, list): - date = [1970,1,1,0,0] - date[:len(t)] = t - t = int(datetime.datetime(date[0],date[1],date[2],date[3],date[4],tzinfo=datetime.timezone.utc).timestamp()) - + t = getNext(t) # going on step forward automatically pads month and day + #date = [1970,1,1,0,0] + #date[:len(t)] = t + #t = int(datetime.datetime(date[0],date[1],date[2],date[3],date[4],tzinfo=datetime.timezone.utc).timestamp()) + t = int(datetime.datetime(t[0],t[1],t[2],tzinfo=datetime.timezone.utc).timestamp()) if (f==None): f = min(timestamps) @@ -801,6 +821,8 @@ def getTimestamps(f,t): + + def getArtistId(nameorid): if isinstance(nameorid,int): return nameorid diff --git a/htmlgenerators.py b/htmlgenerators.py index a7b4f67..39b93ac 100644 --- a/htmlgenerators.py +++ b/htmlgenerators.py @@ -74,7 +74,7 @@ def getTimeDesc(timestamp,short=False): difference = int(difference/60) if difference < 24: return str(difference) + " hours ago" if difference>1 else str(difference) + " hour ago" difference = int(difference/24) - if difference < 7: return tim.strftime("%A") + if difference < 5: return tim.strftime("%A") if difference < 31: return str(difference) + " days ago" if difference>1 else str(difference) + " day ago" #if difference < 300 and tim.year == now.year: return tim.strftime("%B") #if difference < 300: return tim.strftime("%B %Y") diff --git a/scrobbler-vivaldi-plex/manifest.json b/scrobbler-vivaldi-plex/manifest.json index c979cbd..9e8cebe 100644 --- a/scrobbler-vivaldi-plex/manifest.json +++ b/scrobbler-vivaldi-plex/manifest.json @@ -3,7 +3,7 @@ "version": "0.1", "description": "Scrobbles tracks from Plex Web to your Maloja server", "manifest_version": 2, - "permissions": ["activeTab", "declarativeContent","tabs","storage","http://app.plex.tv/*","https://app.plex.tv/*"], + "permissions": ["activeTab", "declarativeContent","tabs","storage","http://app.plex.tv/*","https://app.plex.tv/*",""], "background": { "scripts": diff --git a/website/start.py b/website/start.py index c2929c8..0469a5d 100644 --- a/website/start.py +++ b/website/start.py @@ -26,7 +26,6 @@ def replacedict(keys,dbport): # get chart data # artists - print("REQUESTING " + "http://[::1]:" + str(dbport) + "/charts/artists") response = urllib.request.urlopen("http://[::1]:" + str(dbport) + "/charts/artists") db_data = json.loads(response.read()) charts = db_data["list"][:max_show]