mirror of
https://github.com/krateng/maloja.git
synced 2023-08-10 21:12:55 +03:00
Properly separated servers
This commit is contained in:
parent
08de19459c
commit
dace8f1c44
52
database.py
52
database.py
@ -1,4 +1,4 @@
|
|||||||
from bottle import route, get, post, run, template, static_file, request, response, FormsDict
|
from bottle import Bottle, route, get, post, run, template, static_file, request, response, FormsDict
|
||||||
from importlib.machinery import SourceFileLoader
|
from importlib.machinery import SourceFileLoader
|
||||||
import urllib
|
import urllib
|
||||||
import waitress
|
import waitress
|
||||||
@ -8,6 +8,8 @@ from cleanup import *
|
|||||||
from utilities import *
|
from utilities import *
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
dbserver = Bottle()
|
||||||
|
|
||||||
|
|
||||||
SCROBBLES = [] # Format: tuple(track_ref,timestamp,saved)
|
SCROBBLES = [] # Format: tuple(track_ref,timestamp,saved)
|
||||||
ARTISTS = [] # Format: artist
|
ARTISTS = [] # Format: artist
|
||||||
@ -15,8 +17,8 @@ TRACKS = [] # Format: tuple(frozenset(artist_ref,...),title)
|
|||||||
|
|
||||||
timestamps = set()
|
timestamps = set()
|
||||||
|
|
||||||
c = CleanerAgent()
|
cla = CleanerAgent()
|
||||||
sovereign = CollectorAgent()
|
coa = CollectorAgent()
|
||||||
clients = []
|
clients = []
|
||||||
|
|
||||||
lastsync = 0
|
lastsync = 0
|
||||||
@ -100,7 +102,7 @@ def getTrackID(artists,title):
|
|||||||
## HTTP requests
|
## HTTP requests
|
||||||
####
|
####
|
||||||
|
|
||||||
@route("/test")
|
@dbserver.route("/test")
|
||||||
def test_server():
|
def test_server():
|
||||||
apikey = request.query.get("key")
|
apikey = request.query.get("key")
|
||||||
response.set_header("Access-Control-Allow-Origin","*")
|
response.set_header("Access-Control-Allow-Origin","*")
|
||||||
@ -112,14 +114,14 @@ def test_server():
|
|||||||
response.status = 204
|
response.status = 204
|
||||||
return
|
return
|
||||||
|
|
||||||
@route("/scrobbles")
|
@dbserver.route("/scrobbles")
|
||||||
def get_scrobbles():
|
def get_scrobbles():
|
||||||
keys = request.query
|
keys = request.query
|
||||||
r = db_query(artist=keys.get("artist"),track=keys.get("track"),since=keys.get("since"),to=keys.get("to"))
|
r = db_query(artist=keys.get("artist"),track=keys.get("track"),since=keys.get("since"),to=keys.get("to"))
|
||||||
|
|
||||||
return {"list":r} ##json can't be a list apparently???
|
return {"list":r} ##json can't be a list apparently???
|
||||||
|
|
||||||
@route("/tracks")
|
@dbserver.route("/tracks")
|
||||||
def get_tracks():
|
def get_tracks():
|
||||||
keys = FormsDict.decode(request.query)
|
keys = FormsDict.decode(request.query)
|
||||||
artist = keys.get("artist")
|
artist = keys.get("artist")
|
||||||
@ -136,33 +138,33 @@ def get_tracks():
|
|||||||
|
|
||||||
return {"list":ls}
|
return {"list":ls}
|
||||||
|
|
||||||
@route("/artists")
|
@dbserver.route("/artists")
|
||||||
def get_artists():
|
def get_artists():
|
||||||
|
|
||||||
return {"list":ARTISTS}
|
return {"list":ARTISTS}
|
||||||
|
|
||||||
@route("/charts/artists")
|
@dbserver.route("/charts/artists")
|
||||||
def get_charts_artists():
|
def get_charts_artists():
|
||||||
since = request.query.get("since")
|
since = request.query.get("since")
|
||||||
to = request.query.get("to")
|
to = request.query.get("to")
|
||||||
|
|
||||||
return {"list":db_aggregate(by="ARTIST",since=since,to=to)}
|
return {"list":db_aggregate(by="ARTIST",since=since,to=to)}
|
||||||
|
|
||||||
@route("/charts/tracks")
|
@dbserver.route("/charts/tracks")
|
||||||
def get_charts_tracks():
|
def get_charts_tracks():
|
||||||
since = request.query.get("since")
|
since = request.query.get("since")
|
||||||
to = request.query.get("to")
|
to = request.query.get("to")
|
||||||
|
|
||||||
return {"list":db_aggregate(by="TRACK",since=since,to=to)}
|
return {"list":db_aggregate(by="TRACK",since=since,to=to)}
|
||||||
|
|
||||||
@route("/charts")
|
@dbserver.route("/charts")
|
||||||
def get_charts():
|
def get_charts():
|
||||||
since = request.query.get("since")
|
since = request.query.get("since")
|
||||||
to = request.query.get("to")
|
to = request.query.get("to")
|
||||||
|
|
||||||
return {"number":db_aggregate(since=since,to=to)}
|
return {"number":db_aggregate(since=since,to=to)}
|
||||||
|
|
||||||
@route("/pulse")
|
@dbserver.route("/pulse")
|
||||||
def get_pulse():
|
def get_pulse():
|
||||||
since = request.query.get("since")
|
since = request.query.get("since")
|
||||||
to = request.query.get("to")
|
to = request.query.get("to")
|
||||||
@ -194,7 +196,7 @@ def get_pulse():
|
|||||||
return {"list":results}
|
return {"list":results}
|
||||||
|
|
||||||
|
|
||||||
@route("/top/artists")
|
@dbserver.route("/top/artists")
|
||||||
def get_top_artists():
|
def get_top_artists():
|
||||||
since = request.query.get("since")
|
since = request.query.get("since")
|
||||||
to = request.query.get("to")
|
to = request.query.get("to")
|
||||||
@ -228,7 +230,7 @@ def get_top_artists():
|
|||||||
|
|
||||||
return {"list":results}
|
return {"list":results}
|
||||||
|
|
||||||
@route("/top/tracks")
|
@dbserver.route("/top/tracks")
|
||||||
def get_top_tracks():
|
def get_top_tracks():
|
||||||
since = request.query.get("since")
|
since = request.query.get("since")
|
||||||
to = request.query.get("to")
|
to = request.query.get("to")
|
||||||
@ -298,7 +300,7 @@ def getNext(time,unit,step=1):
|
|||||||
elif unit == "week":
|
elif unit == "week":
|
||||||
return getNext(time,"day",step * 7)
|
return getNext(time,"day",step * 7)
|
||||||
|
|
||||||
@route("/artistinfo")
|
@dbserver.route("/artistinfo")
|
||||||
def artistInfo():
|
def artistInfo():
|
||||||
keys = FormsDict.decode(request.query)
|
keys = FormsDict.decode(request.query)
|
||||||
artist = keys.get("artist")
|
artist = keys.get("artist")
|
||||||
@ -307,11 +309,11 @@ def artistInfo():
|
|||||||
scrobbles = len(db_query(artist=artist)) #we cant take the scrobble number from the charts because that includes all countas scrobbles
|
scrobbles = len(db_query(artist=artist)) #we cant take the scrobble number from the charts because that includes all countas scrobbles
|
||||||
try:
|
try:
|
||||||
c = [e for e in charts if e["artist"] == artist][0]
|
c = [e for e in charts if e["artist"] == artist][0]
|
||||||
others = sovereign.getAllAssociated(artist)
|
others = coa.getAllAssociated(artist)
|
||||||
return {"scrobbles":scrobbles,"position":charts.index(c) + 1,"associated":others}
|
return {"scrobbles":scrobbles,"position":charts.index(c) + 1,"associated":others}
|
||||||
except:
|
except:
|
||||||
# if the artist isnt in the charts, they are not being credited and we need to show information about the credited one
|
# if the artist isnt in the charts, they are not being credited and we need to show information about the credited one
|
||||||
artist = sovereign.getCredited(artist)
|
artist = coa.getCredited(artist)
|
||||||
c = [e for e in charts if e["artist"] == artist][0]
|
c = [e for e in charts if e["artist"] == artist][0]
|
||||||
return {"replace":artist,"scrobbles":scrobbles,"position":charts.index(c) + 1}
|
return {"replace":artist,"scrobbles":scrobbles,"position":charts.index(c) + 1}
|
||||||
|
|
||||||
@ -322,7 +324,7 @@ def isPast(date,limit):
|
|||||||
return date[1] > limit[1]
|
return date[1] > limit[1]
|
||||||
return (date[2] > limit[2])
|
return (date[2] > limit[2])
|
||||||
|
|
||||||
@get("/newscrobble")
|
@dbserver.get("/newscrobble")
|
||||||
def pseudo_post_scrobble():
|
def pseudo_post_scrobble():
|
||||||
keys = FormsDict.decode(request.query) # The Dal★Shabet handler
|
keys = FormsDict.decode(request.query) # The Dal★Shabet handler
|
||||||
artists = keys.get("artist")
|
artists = keys.get("artist")
|
||||||
@ -331,7 +333,7 @@ def pseudo_post_scrobble():
|
|||||||
time = int(keys.get("time"))
|
time = int(keys.get("time"))
|
||||||
except:
|
except:
|
||||||
time = int(datetime.datetime.now(tz=datetime.timezone.utc).timestamp())
|
time = int(datetime.datetime.now(tz=datetime.timezone.utc).timestamp())
|
||||||
(artists,title) = c.fullclean(artists,title)
|
(artists,title) = cla.fullclean(artists,title)
|
||||||
|
|
||||||
## this is necessary for localhost testing
|
## this is necessary for localhost testing
|
||||||
response.set_header("Access-Control-Allow-Origin","*")
|
response.set_header("Access-Control-Allow-Origin","*")
|
||||||
@ -343,7 +345,7 @@ def pseudo_post_scrobble():
|
|||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@post("/newscrobble")
|
@dbserver.post("/newscrobble")
|
||||||
def post_scrobble():
|
def post_scrobble():
|
||||||
keys = FormsDict.decode(request.forms) # The Dal★Shabet handler
|
keys = FormsDict.decode(request.forms) # The Dal★Shabet handler
|
||||||
artists = keys.get("artist")
|
artists = keys.get("artist")
|
||||||
@ -357,7 +359,7 @@ def post_scrobble():
|
|||||||
time = int(keys.get("time"))
|
time = int(keys.get("time"))
|
||||||
except:
|
except:
|
||||||
time = int(datetime.datetime.now(tz=datetime.timezone.utc).timestamp())
|
time = int(datetime.datetime.now(tz=datetime.timezone.utc).timestamp())
|
||||||
(artists,title) = c.fullclean(artists,title)
|
(artists,title) = cla.fullclean(artists,title)
|
||||||
|
|
||||||
## this is necessary for localhost testing
|
## this is necessary for localhost testing
|
||||||
response.set_header("Access-Control-Allow-Origin","*")
|
response.set_header("Access-Control-Allow-Origin","*")
|
||||||
@ -369,7 +371,7 @@ def post_scrobble():
|
|||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@route("/sync")
|
@dbserver.route("/sync")
|
||||||
def abouttoshutdown():
|
def abouttoshutdown():
|
||||||
sync()
|
sync()
|
||||||
#sys.exit()
|
#sys.exit()
|
||||||
@ -382,17 +384,17 @@ def abouttoshutdown():
|
|||||||
|
|
||||||
|
|
||||||
# Starts the server
|
# Starts the server
|
||||||
def runserver(DATABASE_PORT):
|
def runserver(PORT):
|
||||||
global lastsync
|
global lastsync
|
||||||
lastsync = time = int(datetime.datetime.now(tz=datetime.timezone.utc).timestamp())
|
lastsync = time = int(datetime.datetime.now(tz=datetime.timezone.utc).timestamp())
|
||||||
#reload()
|
#reload()
|
||||||
#buildh()
|
#buildh()
|
||||||
build_db()
|
build_db()
|
||||||
sovereign.updateIDs(ARTISTS)
|
coa.updateIDs(ARTISTS)
|
||||||
|
|
||||||
loadAPIkeys()
|
loadAPIkeys()
|
||||||
|
|
||||||
run(host='0.0.0.0', port=DATABASE_PORT, server='waitress')
|
run(dbserver, host='0.0.0.0', port=PORT, server='waitress')
|
||||||
|
|
||||||
|
|
||||||
def build_db():
|
def build_db():
|
||||||
@ -496,7 +498,7 @@ def db_aggregate(by=None,since=None,to=None):
|
|||||||
charts = {}
|
charts = {}
|
||||||
for s in [scr for scr in SCROBBLES if since < scr[1] < to]:
|
for s in [scr for scr in SCROBBLES if since < scr[1] < to]:
|
||||||
artists = TRACKS[s[0]][0]
|
artists = TRACKS[s[0]][0]
|
||||||
for a in sovereign.getCreditedList(artists):
|
for a in coa.getCreditedList(artists):
|
||||||
# this either creates the new entry or increments the existing one
|
# this either creates the new entry or increments the existing one
|
||||||
charts[a] = charts.setdefault(a,0) + 1
|
charts[a] = charts.setdefault(a,0) + 1
|
||||||
|
|
||||||
|
35
server.py
35
server.py
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from bottle import route, get, post, run, template, static_file, request, response, FormsDict
|
from bottle import Bottle, route, get, post, error, run, template, static_file, request, response, FormsDict
|
||||||
from importlib.machinery import SourceFileLoader
|
from importlib.machinery import SourceFileLoader
|
||||||
import _thread
|
import _thread
|
||||||
import waitress
|
import waitress
|
||||||
@ -15,18 +15,19 @@ import os
|
|||||||
MAIN_PORT = 42010
|
MAIN_PORT = 42010
|
||||||
DATABASE_PORT = 42011
|
DATABASE_PORT = 42011
|
||||||
|
|
||||||
|
webserver = Bottle()
|
||||||
|
|
||||||
@route("")
|
|
||||||
@route("/")
|
@webserver.route("")
|
||||||
|
@webserver.route("/")
|
||||||
def mainpage():
|
def mainpage():
|
||||||
return static_file("main.html",root="")
|
return static_file("main.html",root="")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# this is the fallback option. If you run this service behind a reverse proxy, it is recommended to rewrite /db/ requests to the port of the db server
|
# this is the fallback option. If you run this service behind a reverse proxy, it is recommended to rewrite /db/ requests to the port of the db server
|
||||||
# e.g. location /db { rewrite ^/db(.*)$ $1 break; proxy_pass http://yoururl:12349; }
|
# e.g. location /db { rewrite ^/db(.*)$ $1 break; proxy_pass http://yoururl:12349; }
|
||||||
|
|
||||||
@get("/db/<pth:path>")
|
@webserver.get("/db/<pth:path>")
|
||||||
def database_get(pth):
|
def database_get(pth):
|
||||||
keys = FormsDict.decode(request.query) # The Dal★Shabet handler
|
keys = FormsDict.decode(request.query) # The Dal★Shabet handler
|
||||||
keystring = "?"
|
keystring = "?"
|
||||||
@ -43,7 +44,7 @@ def database_get(pth):
|
|||||||
response.status = e.code
|
response.status = e.code
|
||||||
return
|
return
|
||||||
|
|
||||||
@post("/db/<pth:path>")
|
@webserver.post("/db/<pth:path>")
|
||||||
def database_post(pth):
|
def database_post(pth):
|
||||||
response.set_header("Access-Control-Allow-Origin","*")
|
response.set_header("Access-Control-Allow-Origin","*")
|
||||||
try:
|
try:
|
||||||
@ -60,7 +61,7 @@ def database_post(pth):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@route("/exit")
|
@webserver.route("/exit")
|
||||||
def shutdown():
|
def shutdown():
|
||||||
graceful_exit()
|
graceful_exit()
|
||||||
|
|
||||||
@ -70,23 +71,23 @@ def graceful_exit(sig=None,frame=None):
|
|||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
@route("/info/<pth:re:.*\\.jpeg>")
|
@webserver.route("/info/<pth:re:.*\\.jpeg>")
|
||||||
@route("/info/<pth:re:.*\\.jpg>")
|
@webserver.route("/info/<pth:re:.*\\.jpg>")
|
||||||
@route("/info/<pth:re:.*\\.png>")
|
@webserver.route("/info/<pth:re:.*\\.png>")
|
||||||
def static_image(pth):
|
def static_image(pth):
|
||||||
return static_file("info/" + pth,root="")
|
return static_file("info/" + pth,root="")
|
||||||
|
|
||||||
@route("/<name:re:.*\\.html>")
|
@webserver.route("/<name:re:.*\\.html>")
|
||||||
@route("/<name:re:.*\\.js>")
|
@webserver.route("/<name:re:.*\\.js>")
|
||||||
@route("/<name:re:.*\\.css>")
|
@webserver.route("/<name:re:.*\\.css>")
|
||||||
@route("/<name:re:.*\\.png>")
|
@webserver.route("/<name:re:.*\\.png>")
|
||||||
@route("/<name:re:.*\\.jpeg>")
|
@webserver.route("/<name:re:.*\\.jpeg>")
|
||||||
def static(name):
|
def static(name):
|
||||||
return static_file("website/" + name,root="")
|
return static_file("website/" + name,root="")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@route("/<name>")
|
@webserver.route("/<name>")
|
||||||
def static_html(name):
|
def static_html(name):
|
||||||
keys = FormsDict.decode(request.query)
|
keys = FormsDict.decode(request.query)
|
||||||
|
|
||||||
@ -117,4 +118,4 @@ except:
|
|||||||
## start database server
|
## start database server
|
||||||
_thread.start_new_thread(SourceFileLoader("database","database.py").load_module().runserver,(DATABASE_PORT,))
|
_thread.start_new_thread(SourceFileLoader("database","database.py").load_module().runserver,(DATABASE_PORT,))
|
||||||
|
|
||||||
run(host='0.0.0.0', port=MAIN_PORT, server='waitress')
|
run(webserver, host='0.0.0.0', port=MAIN_PORT, server='waitress')
|
||||||
|
@ -123,11 +123,14 @@ def getArtistInfo(artist):
|
|||||||
imgurl
|
imgurl
|
||||||
except NameError:
|
except NameError:
|
||||||
imgurl = lastfm_data["artist"]["image"][2]["#text"]
|
imgurl = lastfm_data["artist"]["image"][2]["#text"]
|
||||||
_thread.start_new_thread(cacheImage,(imgurl,"info/artists_cache",filename))
|
if imgurl == "":
|
||||||
|
imgurl = "/info/artists/default.jpg"
|
||||||
|
else:
|
||||||
|
_thread.start_new_thread(cacheImage,(imgurl,"info/artists_cache",filename))
|
||||||
try:
|
try:
|
||||||
desc
|
desc
|
||||||
except NameError:
|
except NameError:
|
||||||
desc = lastfm_data["artist"]["bio"]["summary"]
|
desc = lastfm_data["artist"]["bio"]["summary"].split("(1) ")[-1]
|
||||||
with open(filepath_cache + ".txt","w") as descfile:
|
with open(filepath_cache + ".txt","w") as descfile:
|
||||||
descfile.write(desc)
|
descfile.write(desc)
|
||||||
# this feels so dirty
|
# this feels so dirty
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<span>KEY_ASSOCIATED</span>
|
<span>KEY_ASSOCIATED</span>
|
||||||
<p class="stats">KEY_SCROBBLES Scrobbles</p>
|
<p class="stats">KEY_SCROBBLES Scrobbles</p>
|
||||||
|
|
||||||
KEY_DESCRIPTION
|
<p>KEY_DESCRIPTION</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
@ -16,6 +16,7 @@ a:hover {
|
|||||||
text-decoration:underline;
|
text-decoration:underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
table.top_info td.image {
|
table.top_info td.image {
|
||||||
padding:20px;
|
padding:20px;
|
||||||
padding-left:0px;
|
padding-left:0px;
|
||||||
|
28
website/scrobbles.html
Normal file
28
website/scrobbles.html
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Maloja - Scrobbles</title>
|
||||||
|
<link rel="stylesheet" href="maloja.css" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table class="top_info">
|
||||||
|
<tr>
|
||||||
|
<td class="image">
|
||||||
|
<div style="background-image:url('KEY_IMAGEURL')"></div>
|
||||||
|
</td>
|
||||||
|
<td class="text">
|
||||||
|
<h1>Scrobbles</h1><br/>
|
||||||
|
<span>KEY_LIMITS</span>
|
||||||
|
<p class="stats">KEY_SCROBBLES Scrobbles</p>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
KEY_SCROBBLELIST
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user