mirror of
https://github.com/krateng/maloja.git
synced 2025-06-19 16:23:57 +03:00
Merged master changes into branch
This commit is contained in:
commit
de02c53e52
@ -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.
|
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?
|
### 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.
|
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
|
## 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:
|
1) Install the requirements:
|
||||||
|
|
||||||
|
@ -739,6 +739,9 @@ def build_db():
|
|||||||
global db_rulestate
|
global db_rulestate
|
||||||
db_rulestate = consistentRulestate("scrobbles",cla.checksums)
|
db_rulestate = consistentRulestate("scrobbles",cla.checksums)
|
||||||
|
|
||||||
|
# load cached images
|
||||||
|
loadCache()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -775,6 +778,9 @@ def sync():
|
|||||||
lastsync = int(datetime.datetime.now(tz=datetime.timezone.utc).timestamp())
|
lastsync = int(datetime.datetime.now(tz=datetime.timezone.utc).timestamp())
|
||||||
log("Database saved to disk.")
|
log("Database saved to disk.")
|
||||||
|
|
||||||
|
# save cached images
|
||||||
|
saveCache()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1
images/.gitignore
vendored
Normal file
1
images/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
cache
|
121
maloja
121
maloja
@ -1,22 +1,115 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import signal
|
||||||
|
import os
|
||||||
|
import stat
|
||||||
|
|
||||||
|
|
||||||
neededmodules = [
|
neededmodules = [
|
||||||
"bottle",
|
"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:
|
try:
|
||||||
exec("import " + m) #I'm sorry
|
output = subprocess.check_output(["pidof","Maloja"])
|
||||||
|
pid = int(output)
|
||||||
|
return pid
|
||||||
except:
|
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
|
||||||
|
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
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!")
|
|
||||||
|
14
server.py
14
server.py
@ -12,6 +12,7 @@ from urllib.error import *
|
|||||||
import sys
|
import sys
|
||||||
import signal
|
import signal
|
||||||
import os
|
import os
|
||||||
|
import setproctitle
|
||||||
|
|
||||||
|
|
||||||
MAIN_PORT = 42010
|
MAIN_PORT = 42010
|
||||||
@ -63,12 +64,9 @@ def database_post(pth):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@webserver.route("/exit")
|
|
||||||
def shutdown():
|
|
||||||
graceful_exit()
|
|
||||||
|
|
||||||
def graceful_exit(sig=None,frame=None):
|
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...")
|
log("Server shutting down...")
|
||||||
os._exit(42)
|
os._exit(42)
|
||||||
|
|
||||||
@ -117,12 +115,8 @@ def static_html(name):
|
|||||||
signal.signal(signal.SIGINT, graceful_exit)
|
signal.signal(signal.SIGINT, graceful_exit)
|
||||||
signal.signal(signal.SIGTERM, graceful_exit)
|
signal.signal(signal.SIGTERM, graceful_exit)
|
||||||
|
|
||||||
#rename process, not important
|
#rename process, this is now required for the daemon manager to work
|
||||||
try:
|
setproctitle.setproctitle("Maloja")
|
||||||
import setproctitle
|
|
||||||
setproctitle.setproctitle("Maloja")
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
## 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,))
|
||||||
|
20
utilities.py
20
utilities.py
@ -2,6 +2,7 @@ import re
|
|||||||
import os
|
import os
|
||||||
import hashlib
|
import hashlib
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
import pickle
|
||||||
|
|
||||||
|
|
||||||
### TSV files
|
### TSV files
|
||||||
@ -229,6 +230,25 @@ def apirequest(artists=None,artist=None,title=None):
|
|||||||
cachedTracks = {}
|
cachedTracks = {}
|
||||||
cachedArtists = {}
|
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):
|
def getTrackInfo(artists,title):
|
||||||
|
|
||||||
obj = (frozenset(artists),title)
|
obj = (frozenset(artists),title)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user