Merged master changes into branch

This commit is contained in:
Krateng 2019-02-16 21:36:42 +01:00
commit de02c53e52
6 changed files with 139 additions and 29 deletions

View File

@ -12,10 +12,6 @@ Maloja is self-hosted. You will always be able to access your data, and not have
Maloja gets rid of all the extra stuff: social networking, radios, recommendations, etc. It only keeps track of your listening history and lets you analyze it. This focus on its core allows it to potentially implement much better database features. One example: Maloja supports multiple artists per track. This means artists who are often just "featuring" in the track title get a place in your charts, and collaborations between several artists finally get credited to all participants.
### Why not use the established API?
Compatibility creates overhead effort. I only made this for myself, so I have no need to support lots of music players and scrobblers. Maloja has a significantly smaller API that allows it to be much simpler and implement its additional features.
### Why Maloja?
I like to name my projects after regions in Grisons, Switzerland. Don't waste your time trying to find a connection, I just picked one at random. Do visit Maloja though. It's a great pass to drive.
@ -28,7 +24,7 @@ The software works fairly well and has a few web views, but there is only one sc
## How to install
Installing Maloja is fairly easy on a Linux machine. Don't ask me how to do it on Windows, I have no clue.
Installing Maloja is fairly easy on a Linux machine. Don't ask me how to do it on Windows, I have no clue. Don't ask me to add any lines to make it work on Windows either, the code is already shitty enough.
1) Install the requirements:

View File

@ -739,6 +739,9 @@ def build_db():
global db_rulestate
db_rulestate = consistentRulestate("scrobbles",cla.checksums)
# load cached images
loadCache()
@ -774,6 +777,9 @@ def sync():
global lastsync
lastsync = int(datetime.datetime.now(tz=datetime.timezone.utc).timestamp())
log("Database saved to disk.")
# save cached images
saveCache()

1
images/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
cache

121
maloja
View File

@ -1,22 +1,115 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import subprocess
import sys
import signal
import os
import stat
neededmodules = [
"bottle",
"waitress"
"waitress",
"setproctitle"
]
toinstall = []
for m in neededmodules:
SOURCE_URL = "https://github.com/krateng/maloja/archive/master.zip"
def install():
toinstall = []
for m in neededmodules:
try:
exec("import " + m) #I'm sorry
except:
toinstall.append(m)
if toinstall != []:
print("The following python modules need to be installed:")
for m in toinstall:
print("\t" + m)
else:
return
def getInstance():
try:
exec("import " + m) #I'm sorry
output = subprocess.check_output(["pidof","Maloja"])
pid = int(output)
return pid
except:
toinstall.append(m)
return None
def start():
install()
try:
p = subprocess.Popen(["python3","server.py"],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
print("Maloja started! PID: " + str(p.pid))
return True
except:
print("Error while starting Maloja. Are you sure it's not already running?")
return False
if toinstall != []:
print("The following python modules need to be installed:")
for m in toinstall:
print("\t" + m)
else:
import subprocess
subprocess.Popen(["python","server.py"],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
print("Maloja started!")
def restart():
#pid = getInstance()
#if pid == None:
# print("Server is not running.")
#else:
# stop()
#start()
wasrunning = stop()
start()
return wasrunning
def stop():
pid = getInstance()
if pid == None:
print("Server is not running")
return False
else:
print("Stopping " + str(pid))
os.kill(pid,signal.SIGTERM)
return True
def update():
import urllib.request
import shutil
import tempfile
import zipfile
import distutils.dir_util
print("Updating Maloja...")
with urllib.request.urlopen(SOURCE_URL) as response:
with tempfile.NamedTemporaryFile(delete=True) as tmpfile:
shutil.copyfileobj(response,tmpfile)
with zipfile.ZipFile(tmpfile.name,"r") as z:
for f in z.namelist():
print("extracting " + f)
z.extract(f)
distutils.dir_util.copy_tree("./maloja-master/","./",verbose=2)
shutil.rmtree("./maloja-master")
print("Done!")
os.chmod("./maloja",os.stat("./maloja").st_mode | stat.S_IXUSR)
if stop(): start() #stop returns whether it was running before, in which case we restart it
if __name__ == "__main__":
if sys.argv[1] == "start": start()
elif sys.argv[1] == "restart": restart()
elif sys.argv[1] == "stop": stop()
elif sys.argv[1] == "update": update()

View File

@ -12,6 +12,7 @@ from urllib.error import *
import sys
import signal
import os
import setproctitle
MAIN_PORT = 42010
@ -63,12 +64,9 @@ def database_post(pth):
return
@webserver.route("/exit")
def shutdown():
graceful_exit()
def graceful_exit(sig=None,frame=None):
urllib.request.urlopen("http://localhost:" + str(DATABASE_PORT) + "/sync")
urllib.request.urlopen("http://[::1]:" + str(DATABASE_PORT) + "/sync")
log("Server shutting down...")
os._exit(42)
@ -117,12 +115,8 @@ def static_html(name):
signal.signal(signal.SIGINT, graceful_exit)
signal.signal(signal.SIGTERM, graceful_exit)
#rename process, not important
try:
import setproctitle
setproctitle.setproctitle("Maloja")
except:
pass
#rename process, this is now required for the daemon manager to work
setproctitle.setproctitle("Maloja")
## start database server
_thread.start_new_thread(SourceFileLoader("database","database.py").load_module().runserver,(DATABASE_PORT,))

View File

@ -2,6 +2,7 @@ import re
import os
import hashlib
from threading import Thread
import pickle
### TSV files
@ -229,6 +230,25 @@ def apirequest(artists=None,artist=None,title=None):
cachedTracks = {}
cachedArtists = {}
def saveCache():
fl = open("images/cache","wb")
stream = pickle.dumps((cachedTracks,cachedArtists))
fl.write(stream)
fl.close()
def loadCache():
try:
fl = open("images/cache","rb")
except:
return
try:
ob = pickle.loads(fl.read())
global cachedTracks, cachedArtists
(cachedTracks, cachedArtists) = ob
finally:
fl.close()
def getTrackInfo(artists,title):
obj = (frozenset(artists),title)