Reorganized backend

This commit is contained in:
Krateng 2020-07-30 15:31:29 +02:00
parent c44e14d0a6
commit 3e1331b0e3
8 changed files with 285 additions and 299 deletions

View File

@ -0,0 +1,123 @@
function keyDetect(event) {
if (event.key === "Enter" || event.key === "Tab") { addArtist() }
if (event.key === "Backspace" && document.getElementById("artists").value == "") { removeArtist() }
}
function addArtist() {
element = document.getElementById("artists");
newartist = element.value.trim();
element.value = "";
if (newartist != "") {
artist = document.createElement("span");
artist.innerHTML = newartist;
artist.style = "padding:5px;";
document.getElementById("artists_td").insertBefore(artist,element);
element.placeholder = "Backspace to remove last"
}
}
function removeArtist() {
artists = document.getElementById("artists_td").getElementsByTagName("span")
lastartist = artists[artists.length-1]
document.getElementById("artists_td").removeChild(lastartist);
if (artists.length < 1) {
document.getElementById("artists").placeholder = "Separate with Enter"
}
}
function scrobbleIfEnter(event) {
if (event.key === "Enter") {
scrobbleNew()
}
}
function scrobbleNew() {
artistnodes = document.getElementById("artists_td").getElementsByTagName("span");
artists = [];
for (let node of artistnodes) {
artists.push(node.innerHTML);
}
title = document.getElementById("title").value;
scrobble(artists,title);
}
function scrobble(artists,title) {
artist = artists.join(";");
if (title != "" && artists.length > 0) {
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = scrobbledone
xhttp.open("GET","/api/newscrobble?artist=" + encodeURIComponent(artist) +
"&title=" + encodeURIComponent(title), true);
xhttp.send();
}
document.getElementById("title").value = "";
document.getElementById("artists").value = "";
parent = document.getElementById("artists_td");
artists = document.getElementById("artists_td").getElementsByTagName("span")
while (artists.length > 0) {
removeArtist();
}
}
function scrobbledone() {
if (this.readyState == 4 && this.status == 200) {
result = JSON.parse(this.responseText);
txt = result["track"]["title"] + " by " + result["track"]["artists"][0];
if (result["track"]["artists"].length > 1) {
txt += " et al.";
}
document.getElementById("notification").innerHTML = "Scrobbled " + txt + "!";
}
}
///
// SEARCH
///
function search_manualscrobbling(searchfield) {
txt = searchfield.value;
if (txt == "") {
}
else {
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = searchresult_manualscrobbling;
xhttp.open("GET","/api/search?max=5&query=" + encodeURIComponent(txt), true);
xhttp.send();
}
}
function searchresult_manualscrobbling() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("searchresults").innerHTML = "";
result = JSON.parse(this.responseText);
tracks = result["tracks"].slice(0,10);
console.log(tracks);
for (let t of tracks) {
track = document.createElement("span");
trackstr = t["artists"].join(", ") + " - " + t["title"];
tracklink = t["link"];
track.innerHTML = "<a href='" + tracklink + "'>" + trackstr + "</a>";
row = document.createElement("tr")
col1 = document.createElement("td")
col1.className = "button"
col1.innerHTML = "Scrobble!"
col1.onclick = function(){ scrobble(t["artists"],t["title"])};
col2 = document.createElement("td")
row.appendChild(col1)
row.appendChild(col2)
col2.appendChild(track)
document.getElementById("searchresults").appendChild(row);
}
}
}

View File

@ -1,54 +1,5 @@
{% extends "base.jinja" %} {% extends "base.jinja" %}
{% block title %}Maloja - Admin Panel{% endblock %} {% block title %}Maloja - Backend{% endblock %}
{% block scripts %}
<script src="/cookies.js"></script>
<script>
function versioncompare(a,b) {
for (var pos=0;pos<3;pos++) {
var v1 = parseInt(a[pos]) || 0;
var v2 = parseInt(b[pos]) || 0;
if (v1 > v2) { return 1;}
if (v1 < v2) { return -1;}
}
return 0;
}
neo.xhttprequest("https://pypi.org/pypi/malojaserver/json",{},"GET",json=true).then((response)=>{
result = JSON.parse(response.responseText);
latestvers = result.info.version.split(".");
neo.xhttprequest("/api/serverinfo",{},"GET",json=true).then((response)=>{
result = JSON.parse(response.responseText);
thisvers = result.version;
document.getElementById("latestversion").innerHTML = latestvers.join(".");
document.getElementById("currentversion").innerHTML = thisvers.join(".");
if (versioncompare(latestvers,thisvers) <= 0) {
document.getElementById("currentversion").style.color = "green";
}
else {
document.getElementById("currentversion").style.color = "red";
document.getElementById("updatestatus").innerHTML = "Consider updating to take advantage of new features";
}
});
});
function activate() {
neo.setCookie("adminmode","true");
window.location.reload(true);
}
function deactivate() {
neo.setCookie("adminmode","false");
window.location.reload(true);
}
</script>
{% endblock %}
{% block content %} {% block content %}
@ -63,36 +14,36 @@
</td> </td>
<td class="text"> <td class="text">
<h1>Admin Panel</h1> <h1>Admin Panel</h1>
<br/>
<span>
{% if page=='admin_overview' %}
<span style="opacity:0.5;">Overview</span>
{% else %}
<a href="/admin_overview">Overview</a>
{% endif %} |
{% if page=='admin_setup' %}
<span style="opacity:0.5;">Server Setup</span>
{% else %}
<a href="/admin_setup">Server Setup</a>
{% endif %} |
{% if page=='admin_manual' %}
<span style="opacity:0.5;">Manual Scrobbling</span>
{% else %}
<a href="/admin_manual">Manual Scrobbling</a>
{% endif %} |
{% if page=='admin_issues' %}
<span style="opacity:0.5;">Database Maintenance</span>
{% else %}
<a href="/admin_issues">Database Maintenance</a>
{% endif %}
</span>
<br/><br/>
<span id="notification"></span>
</td> </td>
</tr> </tr>
</table> </table>
<h2>Update</h2> {% block maincontent %}
{% endblock %}
Currently installed Maloja version: <span id="currentversion">Loading...</span><br/>
Latest recommended Maloja version: <span id="latestversion">Loading...</span><br/>
<span id="updatestatus"></span>
<h2>Admin Mode</h2>
Admin Mode allows you to manually scrobble from various places on the web interface instead of just the dedicated page.<br/><br/>
{% if adminmode %}
<span id="adminmodebutton" class="button" onclick="deactivate()">Deactivate</span>
{% else %}
<span id="adminmodebutton" class="button" onclick="activate()">Activate</span>
{% endif %}
<h2>Links</h2>
<a class="textlink" href="/setup">Server Setup</a><br/>
<a class="textlink" href="/manual">Manual Scrobbling</a><br/>
<a class="textlink" href="/issues">Database Maintenance</a>
<h2>External</h2>
<a class="textlink" target="_blank" rel="noopener noreferrer" href="https://github.com/krateng/maloja/issues/new">Report Issue</a><br/>
{% endblock %} {% endblock %}

View File

@ -1,9 +1,9 @@
{% extends "base.jinja" %} {% set page ='admin_issues' %}
{% extends "admin.jinja" %}
{% block title %}Maloja - Issues{% endblock %} {% block title %}Maloja - Issues{% endblock %}
{% block scripts %} {% block scripts %}
<script src="/cookies.js"></script>
<script> <script>
function newrule() { function newrule() {
keys = "" keys = ""
@ -34,22 +34,10 @@
{% set issuedata = dbp.issues() %} {% set issuedata = dbp.issues() %}
{% block content %} {% block maincontent %}
<table class="top_info">
<tr>
<td class="image">
<div style="background-image:url('/favicon.png')"></div>
</td>
<td class="text">
<h1>Possible Issues</h1><br/>
<span>with your library</span>
<!--<p class="stats">KEY_ISSUES Issues</p>-->
<p>Maloja can identify possible problems with consistency or redundancy in your library. After making any changes, you should <a class="textlink" onclick='fullrebuild()'>rebuild your library</a>.</p> <p>Maloja can identify possible problems with consistency or redundancy in your library. After making any changes, you should <a class="textlink" onclick='fullrebuild()'>rebuild your library</a>.</p>
</td>
</tr>
</table>
<table class="list"> <table class="list">

View File

@ -0,0 +1,46 @@
{% set page ='admin_manual' %}
{% extends "admin.jinja" %}
{% block title %}Maloja - Manual Scrobbling{% endblock %}
{% block scripts %}
<script src="/manualscrobble.js"></script>
{% endblock %}
{% block maincontent %}
<h2>Scrobble new discovery</h2>
<table>
<tr>
<td style="padding-right:7px;">
Artists:
</td><td id="artists_td">
<input placeholder='Separate with Enter' class='simpleinput' id='artists' onKeydown='keyDetect(event)' />
</td>
</tr>
<tr>
<td style="padding-right:7px;">
Title:
</td><td>
<input placeholder='Enter to scrobble' class='simpleinput' id='title' onKeydown='scrobbleIfEnter(event)' />
</td>
</tr>
</table>
<br/>
<span class="button" onclick="scrobbleNew(event)">Scrobble!</span>
<br/>
<h2>Search</h2>
<input class="simpleinput" placeholder='Search for a track' oninput='search_manualscrobbling(this)' />
<br/><br/>
<table id="searchresults"></table>
{% endblock %}

View File

@ -0,0 +1,77 @@
{% set page ='admin_overview' %}
{% extends "admin.jinja" %}
{% block title %}Maloja - Admin Panel{% endblock %}
{% block scripts %}
<script>
function versioncompare(a,b) {
for (var pos=0;pos<3;pos++) {
var v1 = parseInt(a[pos]) || 0;
var v2 = parseInt(b[pos]) || 0;
if (v1 > v2) { return 1;}
if (v1 < v2) { return -1;}
}
return 0;
}
neo.xhttprequest("https://pypi.org/pypi/malojaserver/json",{},"GET",json=true).then((response)=>{
result = JSON.parse(response.responseText);
latestvers = result.info.version.split(".");
neo.xhttprequest("/api/serverinfo",{},"GET",json=true).then((response)=>{
result = JSON.parse(response.responseText);
thisvers = result.version;
document.getElementById("latestversion").innerHTML = latestvers.join(".");
document.getElementById("currentversion").innerHTML = thisvers.join(".");
if (versioncompare(latestvers,thisvers) <= 0) {
document.getElementById("currentversion").style.color = "green";
}
else {
document.getElementById("currentversion").style.color = "red";
document.getElementById("updatestatus").innerHTML = "Consider updating to take advantage of new features";
}
});
});
function activate() {
neo.setCookie("adminmode","true");
window.location.reload(true);
}
function deactivate() {
neo.setCookie("adminmode","false");
window.location.reload(true);
}
</script>
{% endblock %}
{% block maincontent %}
<h2>Update</h2>
Currently installed Maloja version: <span id="currentversion">Loading...</span><br/>
Latest recommended Maloja version: <span id="latestversion">Loading...</span><br/>
<span id="updatestatus"></span>
<h2>Admin Mode</h2>
Admin Mode allows you to manually scrobble from various places on the web interface instead of just the dedicated page.<br/><br/>
{% if adminmode %}
<span id="adminmodebutton" class="button" onclick="deactivate()">Deactivate</span>
{% else %}
<span id="adminmodebutton" class="button" onclick="activate()">Activate</span>
{% endif %}
<h2>Links</h2>
<a class="textlink" target="_blank" rel="noopener noreferrer" href="https://github.com/krateng/maloja/issues/new">Report Issue</a><br/>
<a class="textlink" target="_blank" rel="noopener noreferrer" href="https://github.com/krateng/maloja/blob/master/README.md">Readme</a><br/>
<a class="textlink" target="_blank" rel="noopener noreferrer" href="https://pypi.org/project/malojaserver/">PyPi</a><br/>
{% endblock %}

View File

@ -1,8 +1,8 @@
{% extends "base.jinja" %} {% set page ='admin_setup' %}
{% extends "admin.jinja" %}
{% block title %}Maloja - Setup{% endblock %} {% block title %}Maloja - Setup{% endblock %}
{% block scripts %} {% block scripts %}
<script src="/cookies.js"></script>
<script> <script>
@ -49,22 +49,9 @@
{% set rulesets = dbp.get_predefined_rulesets() %} {% set rulesets = dbp.get_predefined_rulesets() %}
{% block content %} {% block maincontent %}
<table class="top_info">
<tr>
<td class="image">
<div style="background-image:url('/favicon.png')"></div>
</td>
<td class="text">
<h1>Maloja</h1><br/>
<p class="desc">Welcome to your own Maloja server!</p>
</td>
</tr>
</table>
<h2>Start Scrobbling</h2> <h2>Start Scrobbling</h2>
If you use Vivaldi, Brave, Iridium or any other Chromium-based browser and listen to music on Plex or YouTube Music, download the extension and simply enter the server URL as well as your API key in the relevant fields. They will turn green if the server is accessible. If you use Vivaldi, Brave, Iridium or any other Chromium-based browser and listen to music on Plex or YouTube Music, download the extension and simply enter the server URL as well as your API key in the relevant fields. They will turn green if the server is accessible.
@ -85,7 +72,7 @@
<tr> <td>seconds</td> <td><i>Duration of Scrobble - optional and currently not used</i></td> </tr> <tr> <td>seconds</td> <td><i>Duration of Scrobble - optional and currently not used</i></td> </tr>
</table> </table>
<br/><br/> <br/><br/>
Finally, you could always <a class="textlink" href="/manual">manually scrobble</a>! Finally, you could always <a class="textlink" href="/admin_manual">manually scrobble</a>!
<br/><br/> <br/><br/>
@ -96,7 +83,7 @@
<h2>Set up some rules</h2> <h2>Set up some rules</h2>
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="/admin_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!
@ -129,7 +116,7 @@
<h2>Say thanks</h2> <h2>Say thanks</h2>
Donations are never required, but always appreciated. If you really like Maloja, you can fund my next Buttergipfel via Donations are never required, but always appreciated. If you really like Maloja, you can fund my next Buttergipfel via
<a class="textlink" target="_blank" rel="noopener noreferrer" href="https://paypal.me/krateng">PayPal</a>, <a class="textlink" href="bitcoin:1krat8JMniJBTiHftMfR1LtF3Y1w5DAxx">Bitcoin</a> or <a class="textlink" href="https://flattr.com/@Krateng">Flattr</a>. <a class="textlink" target="_blank" rel="noopener noreferrer" href="https://paypal.me/krateng">PayPal</a>, <a class="textlink" href="bitcoin:1krat8JMniJBTiHftMfR1LtF3Y1w5DAxx">Bitcoin</a> or <a class="textlink" target="_blank" rel="noopener noreferrer" href="https://flattr.com/@Krateng">Flattr</a>.
<br/><br/> <br/><br/>

View File

@ -48,7 +48,7 @@
</span> </span>
</div> </div>
<a href="/admin"><div title="Server Administration" id="settingsicon"> <a href="/admin_overview"><div title="Server Administration" id="settingsicon">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M17 12.645v-2.289c-1.17-.417-1.907-.533-2.28-1.431-.373-.9.07-1.512.6-2.625l-1.618-1.619c-1.105.525-1.723.974-2.626.6-.9-.374-1.017-1.117-1.431-2.281h-2.29c-.412 1.158-.53 1.907-1.431 2.28h-.001c-.9.374-1.51-.07-2.625-.6l-1.617 1.619c.527 1.11.973 1.724.6 2.625-.375.901-1.123 1.019-2.281 1.431v2.289c1.155.412 1.907.531 2.28 1.431.376.908-.081 1.534-.6 2.625l1.618 1.619c1.107-.525 1.724-.974 2.625-.6h.001c.9.373 1.018 1.118 1.431 2.28h2.289c.412-1.158.53-1.905 1.437-2.282h.001c.894-.372 1.501.071 2.619.602l1.618-1.619c-.525-1.107-.974-1.723-.601-2.625.374-.899 1.126-1.019 2.282-1.43zm-8.5 1.689c-1.564 0-2.833-1.269-2.833-2.834s1.269-2.834 2.833-2.834 2.833 1.269 2.833 2.834-1.269 2.834-2.833 2.834zm15.5 4.205v-1.077c-.55-.196-.897-.251-1.073-.673-.176-.424.033-.711.282-1.236l-.762-.762c-.52.248-.811.458-1.235.283-.424-.175-.479-.525-.674-1.073h-1.076c-.194.545-.25.897-.674 1.073-.424.176-.711-.033-1.235-.283l-.762.762c.248.523.458.812.282 1.236-.176.424-.528.479-1.073.673v1.077c.544.193.897.25 1.073.673.177.427-.038.722-.282 1.236l.762.762c.521-.248.812-.458 1.235-.283.424.175.479.526.674 1.073h1.076c.194-.545.25-.897.676-1.074h.001c.421-.175.706.034 1.232.284l.762-.762c-.247-.521-.458-.812-.282-1.235s.529-.481 1.073-.674zm-4 .794c-.736 0-1.333-.597-1.333-1.333s.597-1.333 1.333-1.333 1.333.597 1.333 1.333-.597 1.333-1.333 1.333z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M17 12.645v-2.289c-1.17-.417-1.907-.533-2.28-1.431-.373-.9.07-1.512.6-2.625l-1.618-1.619c-1.105.525-1.723.974-2.626.6-.9-.374-1.017-1.117-1.431-2.281h-2.29c-.412 1.158-.53 1.907-1.431 2.28h-.001c-.9.374-1.51-.07-2.625-.6l-1.617 1.619c.527 1.11.973 1.724.6 2.625-.375.901-1.123 1.019-2.281 1.431v2.289c1.155.412 1.907.531 2.28 1.431.376.908-.081 1.534-.6 2.625l1.618 1.619c1.107-.525 1.724-.974 2.625-.6h.001c.9.373 1.018 1.118 1.431 2.28h2.289c.412-1.158.53-1.905 1.437-2.282h.001c.894-.372 1.501.071 2.619.602l1.618-1.619c-.525-1.107-.974-1.723-.601-2.625.374-.899 1.126-1.019 2.282-1.43zm-8.5 1.689c-1.564 0-2.833-1.269-2.833-2.834s1.269-2.834 2.833-2.834 2.833 1.269 2.833 2.834-1.269 2.834-2.833 2.834zm15.5 4.205v-1.077c-.55-.196-.897-.251-1.073-.673-.176-.424.033-.711.282-1.236l-.762-.762c-.52.248-.811.458-1.235.283-.424-.175-.479-.525-.674-1.073h-1.076c-.194.545-.25.897-.674 1.073-.424.176-.711-.033-1.235-.283l-.762.762c.248.523.458.812.282 1.236-.176.424-.528.479-1.073.673v1.077c.544.193.897.25 1.073.673.177.427-.038.722-.282 1.236l.762.762c.521-.248.812-.458 1.235-.283.424.175.479.526.674 1.073h1.076c.194-.545.25-.897.676-1.074h.001c.421-.175.706.034 1.232.284l.762-.762c-.247-.521-.458-.812-.282-1.235s.529-.481 1.073-.674zm-4 .794c-.736 0-1.333-.597-1.333-1.333s.597-1.333 1.333-1.333 1.333.597 1.333 1.333-.597 1.333-1.333 1.333z"/></svg>
</div></a> </div></a>

View File

@ -1,186 +0,0 @@
{% extends "base.jinja" %}
{% block title %}Maloja - Manual Scrobbling{% endblock %}
{% block scripts %}
<script src="/cookies.js"></script>
<script>
function keyDetect(event) {
if (event.key === "Enter" || event.key === "Tab") { addArtist() }
if (event.key === "Backspace" && document.getElementById("artists").value == "") { removeArtist() }
}
function addArtist() {
element = document.getElementById("artists");
newartist = element.value.trim();
element.value = "";
if (newartist != "") {
artist = document.createElement("span");
artist.innerHTML = newartist;
artist.style = "padding:5px;";
document.getElementById("artists_td").insertBefore(artist,element);
element.placeholder = "Backspace to remove last"
}
}
function removeArtist() {
artists = document.getElementById("artists_td").getElementsByTagName("span")
lastartist = artists[artists.length-1]
document.getElementById("artists_td").removeChild(lastartist);
if (artists.length < 1) {
document.getElementById("artists").placeholder = "Separate with Enter"
}
}
function scrobbleIfEnter(event) {
if (event.key === "Enter") {
scrobbleNew()
}
}
function scrobbleNew() {
artistnodes = document.getElementById("artists_td").getElementsByTagName("span");
artists = [];
for (let node of artistnodes) {
artists.push(node.innerHTML);
}
title = document.getElementById("title").value;
scrobble(artists,title);
}
function scrobble(artists,title) {
artist = artists.join(";");
if (title != "" && artists.length > 0) {
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = scrobbledone
xhttp.open("GET","/api/newscrobble?artist=" + encodeURIComponent(artist) +
"&title=" + encodeURIComponent(title), true);
xhttp.send();
}
document.getElementById("title").value = "";
document.getElementById("artists").value = "";
parent = document.getElementById("artists_td");
artists = document.getElementById("artists_td").getElementsByTagName("span")
while (artists.length > 0) {
removeArtist();
}
}
function scrobbledone() {
if (this.readyState == 4 && this.status == 200) {
result = JSON.parse(this.responseText);
txt = result["track"]["title"] + " by " + result["track"]["artists"][0];
if (result["track"]["artists"].length > 1) {
txt += " et al.";
}
document.getElementById("scrobbleresult").innerHTML = "Scrobbled " + txt + "!";
}
}
///
// SEARCH
///
function search_manualscrobbling(searchfield) {
txt = searchfield.value;
if (txt == "") {
}
else {
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = searchresult_manualscrobbling;
xhttp.open("GET","/api/search?max=5&query=" + encodeURIComponent(txt), true);
xhttp.send();
}
}
function searchresult_manualscrobbling() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("searchresults").innerHTML = "";
result = JSON.parse(this.responseText);
tracks = result["tracks"].slice(0,10);
console.log(tracks);
for (let t of tracks) {
track = document.createElement("span");
trackstr = t["artists"].join(", ") + " - " + t["title"];
tracklink = t["link"];
track.innerHTML = "<a href='" + tracklink + "'>" + trackstr + "</a>";
row = document.createElement("tr")
col1 = document.createElement("td")
col1.className = "button"
col1.innerHTML = "Scrobble!"
col1.onclick = function(){ scrobble(t["artists"],t["title"])};
col2 = document.createElement("td")
row.appendChild(col1)
row.appendChild(col2)
col2.appendChild(track)
document.getElementById("searchresults").appendChild(row);
}
}
}
</script>
{% endblock %}
{% block content %}
<table class="top_info">
<tr>
<td class="image">
<div style="background-image:url('/favicon.png')"></div>
</td>
<td class="text">
<h1>Manual Scrobbling</h1><br/>
<br/><br/>
<span id="scrobbleresult"></span>
</td>
</tr>
</table>
<h1>Scrobble new discovery</h1>
<table>
<tr>
<td style="padding-right:7px;">
Artists:
</td><td id="artists_td">
<input placeholder='Separate with Enter' class='simpleinput' id='artists' onKeydown='keyDetect(event)' />
</td>
</tr>
<tr>
<td style="padding-right:7px;">
Title:
</td><td>
<input placeholder='Enter to scrobble' class='simpleinput' id='title' onKeydown='scrobbleIfEnter(event)' />
</td>
</tr>
</table>
<br/>
<span class="button" onclick="scrobbleNew(event)">Scrobble!</span>
<br/>
<h1>Search</h1>
<input class="simpleinput" placeholder='Search for a track' oninput='search_manualscrobbling(this)' />
<br/><br/>
<table id="searchresults"></table>
{% endblock %}