Modularized Javascript

This commit is contained in:
Krateng 2019-03-24 16:04:44 +01:00
parent 3f22d6bc75
commit 011b6f6d91
7 changed files with 203 additions and 167 deletions

View File

@ -670,9 +670,12 @@ def issues():
@dbserver.post("/importrules") @dbserver.post("/importrules")
def import_rulemodule(): def import_rulemodule():
keys = FormsDict.decode(request.forms) keys = FormsDict.decode(request.forms)
apikey = keys.pop("key",None)
if (checkAPIkey(apikey)):
filename = keys.get("filename") filename = keys.get("filename")
remove = keys.get("remove") is not None remove = keys.get("remove") is not None
validchars = "'-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" validchars = "-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
filename = "".join(c for c in filename if c in validchars) filename = "".join(c for c in filename if c in validchars)
if remove: if remove:

View File

@ -1,86 +1,3 @@
<meta name="description" content='Maloja is a self-hosted music scrobble server.' /> <meta name="description" content='Maloja is a self-hosted music scrobble server.' />
<link rel="stylesheet" href="maloja.css" /> <link rel="stylesheet" href="maloja.css" />
<script src="javascript/search.js"></script>
<script>
function search(searchfield) {
txt = searchfield.value;
if (txt == "") {
reallyclear()
}
else {
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = searchresult
xhttp.open("GET","/db/search?max=5&query=" + encodeURIComponent(txt), true);
xhttp.send();
}
}
function searchresult() {
if (this.readyState == 4 && this.status == 200 && document.getElementById("searchinput").value != "") {
// checking if field is empty in case we get an old result coming in that would overwrite our cleared result window
result = JSON.parse(this.responseText);
artists = result["artists"].slice(0,5)
tracks = result["tracks"].slice(0,5)
html = `<div class="searchresults">
<span>Artists</span>
<table class="searchresults_artists">`
for (var i=0;i<artists.length;i++) {
name = artists[i];
uristr = "artist=" + encodeURIComponent(name);
uristr = uristr.replace("'","\\'");
image = "/image?" + uristr;
link = "/artist?" + uristr;
html += `<tr onclick="goto('` + link + `')">
<td class="image" style="background-image:url('` + image + `');"></td>
<td>
<span>` + name + `</span><br/>
</td>
</tr>`
}
html += `</table>
<br/><br/>
<span>Tracks</span>
<table class="searchresults_tracks">`
for (var i=0;i<tracks.length;i++) {
artists = tracks[i]["artists"].join(", ");
title = tracks[i]["title"];
uristr = "title=" + encodeURIComponent(title) + "&" + tracks[i]["artists"].map(x => "artist=" + encodeURIComponent(x)).join("&");
uristr = uristr.replace("'","\\'");
image = "/image?" + uristr;
link = "/track?" + uristr;
html += `<tr onclick="goto('` + link + `')">
<td class="image" style="background-image:url('` + image + `');"></td>
<td>
<span>` + artists + `</span><br/>
<span>` + title + `</span>
</td>
</tr>`
}
html += `</table>
</div>`
document.getElementById("resultwrap").innerHTML = html;
}
}
function clearresults() {
window.setTimeout(reallyclear,500)
}
function reallyclear() {
document.getElementById("resultwrap").innerHTML = "";
}
function goto(link) {
window.location = link
}
</script>

View File

@ -4,9 +4,10 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>Maloja - Issues</title> <title>Maloja - Issues</title>
<script src="javascript/cookies.js"></script>
</head> </head>
<body> <body onload="insertAPIKeyFromCookie()">
<table class="top_info"> <table class="top_info">
<tr> <tr>
@ -27,15 +28,6 @@
<script> <script>
cookies = decodeURIComponent(document.cookie).split(';');
for(var i = 0; i <cookies.length; i++) {
if (cookies[i].startsWith("apikey=")) {
document.getElementById("apikey").value = cookies[i].replace("apikey=","")
checkAPIkey()
}
}
apikeycorrect = false;
function newrule() { function newrule() {
if (apikeycorrect) { if (apikeycorrect) {
@ -69,34 +61,6 @@
} }
function saveAPIkey() {
key = document.getElementById("apikey").value
document.cookie = "apikey=" + encodeURIComponent(key)
}
function checkAPIkey() {
saveAPIkey()
url = "/db/test?key=" + document.getElementById("apikey").value
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && (this.status == 204 || this.status == 205)) {
document.getElementById("apikey").style.backgroundColor = "lawngreen"
apikeycorrect = true
}
else {
document.getElementById("apikey").style.backgroundColor = "red"
apikeycorrect = false
}
};
try {
xhttp.open("GET",url,true);
xhttp.send();
}
catch (e) {
document.getElementById("apikey").style.backgroundColor = "red"
apikeycorrect = false
}
}
</script> </script>
</html> </html>

View File

@ -0,0 +1,44 @@
apikeycorrect = false;
function insertAPIKeyFromCookie() {
cookies = decodeURIComponent(document.cookie).split(';');
for(var i = 0; i <cookies.length; i++) {
cookies[i] = cookies[i].trim()
if (cookies[i].startsWith("apikey=")) {
document.getElementById("apikey").value = cookies[i].replace("apikey=","")
checkAPIkey()
}
}
}
function saveAPIkey() {
key = document.getElementById("apikey").value
document.cookie = "apikey=" + encodeURIComponent(key)
}
function checkAPIkey() {
saveAPIkey()
url = "/db/test?key=" + document.getElementById("apikey").value
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && (this.status == 204 || this.status == 205)) {
document.getElementById("apikey").style.backgroundColor = "lawngreen"
apikeycorrect = true
}
else {
document.getElementById("apikey").style.backgroundColor = "red"
apikeycorrect = false
}
};
try {
xhttp.open("GET",url,true);
xhttp.send();
}
catch (e) {
document.getElementById("apikey").style.backgroundColor = "red"
apikeycorrect = false
}
}

View File

@ -0,0 +1,79 @@
function search(searchfield) {
txt = searchfield.value;
if (txt == "") {
reallyclear()
}
else {
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = searchresult
xhttp.open("GET","/db/search?max=5&query=" + encodeURIComponent(txt), true);
xhttp.send();
}
}
function searchresult() {
if (this.readyState == 4 && this.status == 200 && document.getElementById("searchinput").value != "") {
// checking if field is empty in case we get an old result coming in that would overwrite our cleared result window
result = JSON.parse(this.responseText);
artists = result["artists"].slice(0,5)
tracks = result["tracks"].slice(0,5)
html = `<div class="searchresults">
<span>Artists</span>
<table class="searchresults_artists">`
for (var i=0;i<artists.length;i++) {
name = artists[i];
uristr = "artist=" + encodeURIComponent(name);
uristr = uristr.replace("'","\\'");
image = "/image?" + uristr;
link = "/artist?" + uristr;
html += `<tr onclick="goto('` + link + `')">
<td class="image" style="background-image:url('` + image + `');"></td>
<td>
<span>` + name + `</span><br/>
</td>
</tr>`
}
html += `</table>
<br/><br/>
<span>Tracks</span>
<table class="searchresults_tracks">`
for (var i=0;i<tracks.length;i++) {
artists = tracks[i]["artists"].join(", ");
title = tracks[i]["title"];
uristr = "title=" + encodeURIComponent(title) + "&" + tracks[i]["artists"].map(x => "artist=" + encodeURIComponent(x)).join("&");
uristr = uristr.replace("'","\\'");
image = "/image?" + uristr;
link = "/track?" + uristr;
html += `<tr onclick="goto('` + link + `')">
<td class="image" style="background-image:url('` + image + `');"></td>
<td>
<span>` + artists + `</span><br/>
<span>` + title + `</span>
</td>
</tr>`
}
html += `</table>
</div>`
document.getElementById("resultwrap").innerHTML = html;
}
}
function clearresults() {
window.setTimeout(reallyclear,500)
}
function reallyclear() {
document.getElementById("resultwrap").innerHTML = "";
}
function goto(link) {
window.location = link
}

View File

@ -4,8 +4,11 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>Maloja - Setup</title> <title>Maloja - Setup</title>
<script src="javascript/cookies.js"></script>
<script> <script>
function replaceurls() { function replaceurls() {
url = window.location.origin url = window.location.origin
s = document.getElementsByName("serverurl") s = document.getElementsByName("serverurl")
@ -20,8 +23,11 @@
} }
function activateRuleModule(e,filename) { function activateRuleModule(e,filename) {
if (apikeycorrect) {
keys = "filename=" + encodeURIComponent(filename) keys = "filename=" + encodeURIComponent(filename)
apikey = document.getElementById("apikey").value
keys += "&key=" + encodeURIComponent(apikey)
console.log(keys)
var xhttp = new XMLHttpRequest(); var xhttp = new XMLHttpRequest();
xhttp.open("POST","/db/importrules", true); xhttp.open("POST","/db/importrules", true);
xhttp.send(keys); xhttp.send(keys);
@ -30,9 +36,13 @@
e.getAttributeNode("onclick").value = e.getAttribute("onclick").replace("activate","deactivate") e.getAttributeNode("onclick").value = e.getAttribute("onclick").replace("activate","deactivate")
/* Nobody ever look at this code please */ /* Nobody ever look at this code please */
} }
}
function deactivateRuleModule(e,filename) { function deactivateRuleModule(e,filename) {
if (apikeycorrect) {
keys = "remove&filename=" + encodeURIComponent(filename) keys = "remove&filename=" + encodeURIComponent(filename)
apikey = document.getElementById("apikey").value
keys += "&key=" + encodeURIComponent(apikey)
var xhttp = new XMLHttpRequest(); var xhttp = new XMLHttpRequest();
xhttp.open("POST","/db/importrules", true); xhttp.open("POST","/db/importrules", true);
@ -41,6 +51,7 @@
e.innerHTML = e.innerHTML.replace("Remove","Add") e.innerHTML = e.innerHTML.replace("Remove","Add")
e.getAttributeNode("onclick").value = e.getAttribute("onclick").replace("deactivate","activate") e.getAttributeNode("onclick").value = e.getAttribute("onclick").replace("deactivate","activate")
} }
}
</script> </script>
<style> <style>
@ -53,7 +64,7 @@
</head> </head>
<body onload="replace()"> <body onload="replace();insertAPIKeyFromCookie()">
<table class="top_info"> <table class="top_info">
<tr> <tr>
<td class="image"> <td class="image">
@ -99,7 +110,11 @@
After you've scrobbled for a bit, you might want to check the <a class="textlink" href="/issues">Issues page</a> to see if you need to set up some rules. You can also manually add rules in your server's "rules" directory - just add your own .tsv file and read the instructions on how to declare a rule. After you've scrobbled for a bit, you might want to check the <a class="textlink" href="/issues">Issues page</a> to see if you need to set up some rules. You can also manually add rules in your server's "rules" directory - just add your own .tsv file and read the instructions on how to declare a rule.
<br/><br/> <br/><br/>
You can also set up some predefined rulesets right away! You can also set up some predefined rulesets right away! Enter your API key and click the buttons.
<br/>
API Key:
<input id='apikey' onchange='checkAPIkey()' style='width:300px;'/>
<br/><br/> <br/><br/>
KEY_PREDEFINED_RULESETS KEY_PREDEFINED_RULESETS
@ -117,4 +132,6 @@
Done! Visit <a class="textlink" href="/"><span name="serverurl">yourserver.tld</span></a> (or your public / proxy URL) to look at your overview page. Almost everything is clickable! Done! Visit <a class="textlink" href="/"><span name="serverurl">yourserver.tld</span></a> (or your public / proxy URL) to look at your overview page. Almost everything is clickable!
</body> </body>
</html> </html>

View File

@ -6,9 +6,21 @@ def instructions(keys):
html += "<tr><th></th><th>Module</th><th>Author</th><th>Description</th></tr>" html += "<tr><th></th><th>Module</th><th>Author</th><th>Description</th></tr>"
validchars = "-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
for f in os.listdir("rules/predefined"): for f in os.listdir("rules/predefined"):
if f.endswith(".tsv"): if f.endswith(".tsv"):
rawf = f.replace(".tsv","")
valid = True
for char in rawf:
if char not in validchars:
valid = False
break # don't even show up invalid filenames
if not valid: continue
if not "_" in rawf: continue
try: try:
with open("rules/predefined/" + f) as tsvfile: with open("rules/predefined/" + f) as tsvfile:
line1 = tsvfile.readline() line1 = tsvfile.readline()
@ -16,21 +28,21 @@ def instructions(keys):
if "# NAME: " in line1: if "# NAME: " in line1:
name = line1.replace("# NAME: ","") name = line1.replace("# NAME: ","")
else: name = f else: name = rawf.split("_")[1]
if "# DESC: " in line2: if "# DESC: " in line2:
desc = line2.replace("# DESC: ","") desc = line2.replace("# DESC: ","")
else: desc = "" else: desc = ""
author = f.split("_")[0] author = rawf.split("_")[0]
except: except:
continue continue
html += "<tr>" html += "<tr>"
if os.path.exists("rules/" + f): if os.path.exists("rules/" + f):
html += "<td class='interaction' onclick=deactivateRuleModule(this,'" + f.replace(".tsv","") + "')><a class='textlink'>Remove:</a></td>" html += "<td class='interaction' onclick=deactivateRuleModule(this,'" + rawf + "')><a class='textlink'>Remove:</a></td>"
else: else:
html += "<td class='interaction' onclick=activateRuleModule(this,'" + f.replace(".tsv","") + "')><a class='textlink'>Add:</a></td>" html += "<td class='interaction' onclick=activateRuleModule(this,'" + rawf + "')><a class='textlink'>Add:</a></td>"
html += "<td>" + name + "</td>" html += "<td>" + name + "</td>"
html += "<td>" + author + "</td>" html += "<td>" + author + "</td>"
html += "<td>" + desc + "</td>" html += "<td>" + desc + "</td>"