#!/usr/bin/env python3 import subprocess import sys import signal import os import stat import pathlib neededmodules = [ "bottle", "waitress", "setproctitle", "doreah", "nimrodel" ] recommendedmodules = [ "wand" ] SOURCE_URL = "https://github.com/krateng/maloja/archive/master.zip" def blue(txt): return "\033[94m" + txt + "\033[0m" def green(txt): return "\033[92m" + txt + "\033[0m" def yellow(txt): return "\033[93m" + txt + "\033[0m" ## GOTODIR goes to directory that seems to have a maloja install ## SETUP assumes correct directory. sets settings and key ## INSTALL ignores local files, just installs prerequisites ## START INSTALL - GOTODIR - SETUP - starts process ## RESTART STOP - START ## STOP Stops process ## UPDATE GOTODIR - updates from repo ## LOADLASTFM GOTODIR - imports csv data ## INSTALLHERE makes this directory valid - UPDATE - INSTALL - SETUP def gotodir(): if os.path.exists("./server.py"): return True elif os.path.exists("/opt/maloja/server.py"): os.chdir("/opt/maloja/") return True print("Maloja installation could not be found.") return False def setup(): from doreah import settings # EXTERNAL API KEYS apikeys = { "LASTFM_API_KEY":"Last.fm API Key", "FANARTTV_API_KEY":"Fanart.tv API Key", "SPOTIFY_API_ID":"Spotify Client ID", "SPOTIFY_API_SECRET":"Spotify Client Secret" } print("Various external services can be used to display images. If not enough of them are set up, only local images will be used.") for k in apikeys: key = settings.get_settings(k) if key is None: print("\t" + "Currently not using a " + apikeys[k] + " for image display.") elif key == "ASK": print("\t" + "Please enter your " + apikeys[k] + ". If you do not want to use one at this moment, simply leave this empty and press Enter.") key = input() if key == "": key = None settings.update_settings("settings/settings.ini",{k:key},create_new=True) else: print("\t" + apikeys[k] + " found.") # OWN API KEY if os.path.exists("./clients/authenticated_machines.tsv"): pass else: print("Do you want to set up a key to enable scrobbling? Your scrobble extension needs that key so that only you can scrobble tracks to your database. [Y/n]") answer = input() if answer.lower() in ["y","yes","yea","1","positive","true",""]: import random key = "" for i in range(64): key += str(random.choice(list(range(10)) + list("abcdefghijklmnopqrstuvwxyz") + list("ABCDEFGHIJKLMNOPQRSTUVWXYZ"))) print("Your API Key: " + yellow(key)) with open("./clients/authenticated_machines.tsv","w") as keyfile: keyfile.write(key + "\t" + "Default Generated Key") elif answer.lower() in ["n","no","nay","0","negative","false"]: pass def install(): toinstall = [] toinstallr = [] for m in neededmodules: try: exec("import " + m) #I'm sorry except: toinstall.append(m) for m in recommendedmodules: try: exec("import " + m) except: toinstallr.append(m) if toinstall != []: print("The following python modules need to be installed:") for m in toinstall: print("\t" + yellow(m)) if toinstallr != []: print("The following python modules are highly recommended, some features will not work without them:") for m in toinstallr: print("\t" + yellow(m)) if toinstall != [] or toinstallr != []: if os.geteuid() != 0: print("You can install them with",yellow("pip install -r requirements.txt"),"or Maloja can try to install them automatically. For this, you need to run this script as a root user.") return False else: print("You can install them with",yellow("pip install -r requirements.txt"),"or Maloja can try to install them automatically, This might or might not work / bloat your system / cause a nuclear war.") fail = False if toinstall != []: print("Attempt to install required modules? [Y/n]") answer = input() if answer.lower() in ["y","yes","yea","1","positive","true",""]: for m in toinstall: try: print("Installing " + m + " with pip...") from pip._internal import main as pipmain #os.system("pip3 install " + m) pipmain(["install",m]) print("Success!") except: print("Failure!") fail = True elif answer.lower() in ["n","no","nay","0","negative","false"]: return False #if you dont want to auto install required, you probably dont want to install recommended else: print("What?") return False if toinstallr != []: print("Attempt to install recommended modules? [Y/n]") answer = input() if answer.lower() in ["y","yes","yea","1","positive","true",""]: for m in toinstallr: try: print("Installing " + m + " with pip...") from pip._internal import main as pipmain #os.system("pip3 install " + m) pipmain(["install",m]) print("Success!") except: print("Failure!") fail = True elif answer.lower() in ["n","no","nay","0","negative","false"]: return False else: print("What?") return False if fail: return False print("All modules successfully installed!") print("Run the script again (without root) to start Maloja.") return False else: print("All necessary modules seem to be installed.") return True def getInstance(): try: output = subprocess.check_output(["pidof","Maloja"]) pid = int(output) return pid except: return None def getInstanceSupervisor(): try: output = subprocess.check_output(["pidof","maloja_supervisor"]) pid = int(output) return pid except: return None def start(): if install(): if gotodir(): setup() p = subprocess.Popen(["python3","server.py"],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL) p = subprocess.Popen(["python3","supervisor.py"],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL) print(green("Maloja started!") + " PID: " + str(p.pid)) from doreah import settings port = settings.get_settings("WEB_PORT") print("Visit your server address (Port " + str(port) + ") to see your web interface. Visit /setup to get started.") print("If you're installing this on your local machine, these links should get you there:") print("\t" + blue("http://localhost:" + str(port))) print("\t" + blue("http://localhost:" + str(port) + "/setup")) return True #else: # os.chdir("/opt/maloja/") # p = subprocess.Popen(["python3","server.py"],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL) # print("Maloja started! PID: " + str(p.pid)) # return True print("Error while starting Maloja.") 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_sv = getInstanceSupervisor() if pid_sv is not None: os.kill(pid_sv,signal.SIGTERM) pid = getInstance() if pid is None: print("Server is not running") return False else: os.kill(pid,signal.SIGTERM) print("Maloja stopped! PID: " + str(pid)) return True def update(): import urllib.request import shutil #import tempfile import zipfile import distutils.dir_util if not gotodir(): return False if os.path.exists("./.dev"): print("Better not overwrite the development server!") return 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) os.system("wget " + SOURCE_URL) with zipfile.ZipFile("./master.zip","r") as z: # if we ever have a separate directory for the code # (the calling update script is not the same version as the current # remote repository, so we better add this check just in case) if "source/" in z.namelist(): for f in z.namelist(): if f.startswith("source/"): z.extract(f) for dir,_,files in os.walk("source"): for f in files: origfile = os.path.join(dir,f) newfile = ps.path.join(dir[7:],f) os.renames(origfile,newfile) #also prunes empty directory else: for f in z.namelist(): z.extract(f) os.remove("./master.zip") 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) os.chmod("./update_requirements.sh",os.stat("./update_requirements.sh").st_mode | stat.S_IXUSR) try: returnval = os.system("./update_requirements.sh") assert returnval == 0 except: print("Make sure to update required modules! (" + yellow("./update_requirements.sh") + ")") if stop(): start() #stop returns whether it was running before, in which case we restart it def loadlastfm(): try: filename = sys.argv[2] filename = os.path.abspath(filename) except: print("Please specify a file!") return if gotodir(): if os.path.exists("./scrobbles/lastfmimport.tsv"): print("Already imported Last.FM data. Overwrite? [y/N]") if input().lower() in ["y","yes","yea","1","positive","true"]: pass else: return print("Please wait...") os.system("python3 ./lastfmconverter.py " + filename + " ./scrobbles/lastfmimport.tsv") print("Successfully imported your Last.FM scrobbles!") def installhere(): if len(os.listdir()) > 1: print("You should install Maloja in an empty directory.") return False else: open("server.py","w").close() # if it's cheese, but it works, it ain't cheese update() install() setup() print("Maloja installed! Start with " + yellow("./maloja start")) if __name__ == "__main__": if sys.argv[1] == "start": restart() elif sys.argv[1] == "restart": restart() elif sys.argv[1] == "stop": stop() elif sys.argv[1] == "update": update() elif sys.argv[1] == "import": loadlastfm() elif sys.argv[1] == "install": installhere() else: print("Valid commands: start restart stop update import install")