mirror of
https://github.com/krateng/maloja.git
synced 2023-08-10 21:12:55 +03:00
Adjusted globalconfig to new configuration module
This commit is contained in:
parent
77667e7066
commit
b212e6b921
@ -1,11 +1,39 @@
|
|||||||
import os
|
import os
|
||||||
from doreah.settings import get_settings
|
|
||||||
from doreah.settings import config as settingsconfig
|
from doreah.settings import config as settingsconfig
|
||||||
from doreah.configuration import Configuration
|
from doreah.configuration import Configuration
|
||||||
from doreah.configuration import types as tp
|
from doreah.configuration import types as tp
|
||||||
|
|
||||||
|
|
||||||
|
# USEFUL FUNCS
|
||||||
pthj = os.path.join
|
pthj = os.path.join
|
||||||
|
|
||||||
|
def is_dir_usable(pth):
|
||||||
|
try:
|
||||||
|
os.makedirs(pth,exist_ok=True)
|
||||||
|
os.mknod(pthj(pth,".test"))
|
||||||
|
os.remove(pthj(pth,".test"))
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_env_vars(key,pathsuffix=[]):
|
||||||
|
return [pthj(pth,*pathsuffix) for pth in os.environ.get(key,'').split(':') if pth != '']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# get user dirs from environment
|
||||||
|
user_dirs = {}
|
||||||
|
|
||||||
|
user_dirs["home"] = get_env_vars("HOME")
|
||||||
|
user_dirs["config"] = get_env_vars("XDG_CONFIG_HOME",['maloja'])
|
||||||
|
user_dirs["cache"] = get_env_vars("XDG_CACHE_HOME",['maloja'])
|
||||||
|
user_dirs["data"] = get_env_vars("XDG_DATA_HOME",['maloja'])
|
||||||
|
try:
|
||||||
|
user_data_dir = os.environ["XDG_DATA_HOME"].split(":")[0]
|
||||||
|
assert os.path.exists(user_data_dir)
|
||||||
|
except:
|
||||||
|
user_data_dir = os.path.join(os.environ["HOME"],".local/share/")
|
||||||
|
user_data_dir = pthj(user_data_dir,"maloja")
|
||||||
|
|
||||||
# if DATA_DIRECTORY is specified, this is the directory to use for EVERYTHING, no matter what
|
# if DATA_DIRECTORY is specified, this is the directory to use for EVERYTHING, no matter what
|
||||||
# but with asynnetrical structure, cache and logs in subfolders
|
# but with asynnetrical structure, cache and logs in subfolders
|
||||||
@ -19,115 +47,200 @@ pthj = os.path.join
|
|||||||
# if not, use the first we have permissions for
|
# if not, use the first we have permissions for
|
||||||
# after we decide which to use, fix it in settings to avoid future heuristics
|
# after we decide which to use, fix it in settings to avoid future heuristics
|
||||||
|
|
||||||
try:
|
|
||||||
HOME_DIR = os.environ["XDG_DATA_HOME"].split(":")[0]
|
|
||||||
assert os.path.exists(HOME_DIR)
|
|
||||||
except:
|
|
||||||
HOME_DIR = os.path.join(os.environ["HOME"],".local/share/")
|
|
||||||
usrfol = pthj(HOME_DIR,"maloja")
|
|
||||||
etccfg = '/etc/maloja'
|
|
||||||
varlib = '/var/lib/maloja'
|
|
||||||
varcac = '/var/cache/maloja'
|
|
||||||
varlog = '/var/log/maloja'
|
|
||||||
|
|
||||||
dir_settings = {
|
|
||||||
"config":None,
|
|
||||||
"state":None,
|
|
||||||
"logs":None,
|
|
||||||
"cache":None,
|
|
||||||
# "clients":None,
|
|
||||||
# "rules":None,
|
|
||||||
# "settings":None,
|
|
||||||
# "auth":None,
|
|
||||||
# "backups":None,
|
|
||||||
# "images":None,
|
|
||||||
# "scrobbles":None,
|
|
||||||
# "logs":None,
|
|
||||||
# "cache":None
|
|
||||||
}
|
|
||||||
|
|
||||||
dir_options = {
|
### STEP 1 - find out where the settings file is
|
||||||
"config":[
|
# environment variables
|
||||||
|
maloja_dir_config = os.environ.get("MALOJA_DATA_DIRECTORY") or os.environ.get("MALOJA_DIRECTORY_CONFIG")
|
||||||
|
|
||||||
|
if maloja_dir_config is None:
|
||||||
|
potentialpaths = [
|
||||||
"/etc/maloja",
|
"/etc/maloja",
|
||||||
usrfol
|
user_data_dir
|
||||||
],
|
|
||||||
"state":[
|
|
||||||
"/var/lib/maloja",
|
|
||||||
"/etc/maloja",
|
|
||||||
usrfol
|
|
||||||
],
|
|
||||||
"logs":[
|
|
||||||
"/var/log/maloja",
|
|
||||||
"/etc/maloja/logs",
|
|
||||||
pthj(usrfol,"logs")
|
|
||||||
],
|
|
||||||
"cache":[
|
|
||||||
"/var/cache/maloja",
|
|
||||||
"/etc/maloja/cache",
|
|
||||||
pthj(usrfol,"cache")
|
|
||||||
]
|
]
|
||||||
}
|
# check if it exists anywhere else
|
||||||
|
for pth in potentialpaths:
|
||||||
sentinels = {
|
if os.path.exists(pthj(pth,"settings")):
|
||||||
"config":"settings",
|
maloja_dir_config = pth
|
||||||
"state":"scrobbles",
|
break
|
||||||
"logs":None,
|
# new installation, pick where to put it
|
||||||
"cache":None,
|
else:
|
||||||
}
|
# test if we can write to that location
|
||||||
|
for pth in potentialpaths:
|
||||||
# check environ variables
|
if is_dir_usable(pth):
|
||||||
stng_data = get_settings("DATA_DIRECTORY",files=[],environ_prefix="MALOJA_")
|
maloja_dir_config = pth
|
||||||
if stng_data is not None:
|
|
||||||
dir_settings['config'] = stng_data
|
|
||||||
dir_settings['state'] = stng_data
|
|
||||||
dir_settings['cache'] = pthj(stng_data,'cache')
|
|
||||||
dir_settings['logs'] = pthj(stng_data,'logs')
|
|
||||||
else:
|
|
||||||
dir_settings['config'], dir_settings['state'], dir_settings['cache'], dir_settings['logs'] = get_settings("DIRECTORY_CONFIG","DIRECTORY_STATE","DIRECTORY_LOGS","DIRECTORY_CACHE",files=[],environ_prefix="MALOJA_")
|
|
||||||
# as soon as we know the config directory, we can load from settings file
|
|
||||||
if dir_settings['config'] is not None:
|
|
||||||
settingsfiles = [pthj(dir_settings['config'],'settings','default.ini'),pthj(dir_settings['config'],'settings','settings.ini')]
|
|
||||||
dir_settings['config'], dir_settings['state'], dir_settings['cache'], dir_settings['logs'] = get_settings("DIRECTORY_CONFIG","DIRECTORY_STATE","DIRECTORY_LOGS","DIRECTORY_CACHE",files=settingsfiles,environ_prefix="MALOJA_")
|
|
||||||
|
|
||||||
|
|
||||||
# now to the stuff no setting has explicitly defined
|
|
||||||
for dirtype in dir_settings:
|
|
||||||
if dir_settings[dirtype] is None:
|
|
||||||
for option in dir_options[dirtype]:
|
|
||||||
if os.path.exists(option):
|
|
||||||
# check if this is really the directory used for this category (/etc/maloja could be used for state or just config)
|
|
||||||
if sentinels[dirtype] is None or os.path.exists(pthj(option,sentinels[dirtype])):
|
|
||||||
dir_settings[dirtype] = option
|
|
||||||
break
|
|
||||||
|
|
||||||
# if no directory seems to exist, use the first writable one
|
|
||||||
for dirtype in dir_settings:
|
|
||||||
if dir_settings[dirtype] is None:
|
|
||||||
for option in dir_options[dirtype]:
|
|
||||||
try:
|
|
||||||
os.makedirs(option,exist_ok=True)
|
|
||||||
os.mknod(pthj(option,".test"))
|
|
||||||
os.remove(pthj(option,".test"))
|
|
||||||
dir_settings[dirtype] = option
|
|
||||||
break
|
break
|
||||||
except:
|
else:
|
||||||
pass
|
print("Could not find a proper path to put settings file. Please check your permissions!")
|
||||||
|
|
||||||
|
oldsettingsfile = pthj(maloja_dir_config,"settings","settings.ini")
|
||||||
|
newsettingsfile = pthj(maloja_dir_config,"settings.ini")
|
||||||
|
|
||||||
|
if os.path.exists(oldsettingsfile):
|
||||||
|
os.rename(oldsettingsfile,newsettingsfile)
|
||||||
|
|
||||||
|
|
||||||
assert all((dir_settings[s] is not None) for s in dir_settings)
|
### STEP 2 - create settings object
|
||||||
|
|
||||||
|
|
||||||
|
malojaconfig = Configuration(
|
||||||
|
settings={
|
||||||
|
"Setup":{
|
||||||
|
"data_directory":(tp.String(), "Data Directory", None, "Folder for all user data. Overwrites all choices for specific directories."),
|
||||||
|
"directory_config":(tp.String(), "Config Directory", "/etc/maloja", "Folder for config data. Only applied when global data directory is not set."),
|
||||||
|
"directory_state":(tp.String(), "State Directory", "/var/lib/maloja", "Folder for state data. Only applied when global data directory is not set."),
|
||||||
|
"directory_logs":(tp.String(), "Log Directory", "/var/log/maloja", "Folder for log data. Only applied when global data directory is not set."),
|
||||||
|
"directory_cache":(tp.String(), "Cache Directory", "/var/cache/maloja", "Folder for cache data. Only applied when global data directory is not set."),
|
||||||
|
"skip_setup":(tp.Boolean(), "Skip Setup", False, "Make server setup process non-interactive. Vital for Docker."),
|
||||||
|
"force_password":(tp.String(), "Force Password", None, "On startup, overwrite admin password with this one. This should usually only be done via environment variable in Docker."),
|
||||||
|
"clean_output":(tp.Boolean(), "Avoid Mutable Console Output", False, "Use if console output will be redirected e.g. to a web interface.")
|
||||||
|
},
|
||||||
|
"Debug":{
|
||||||
|
"logging":(tp.Boolean(), "Enable Logging", True),
|
||||||
|
"dev_mode":(tp.Boolean(), "Enable developer mode", False),
|
||||||
|
},
|
||||||
|
"Network":{
|
||||||
|
"host":(tp.String(), "Host", "::", "Host for your server - most likely :: for IPv6 or 0.0.0.0 for IPv4"),
|
||||||
|
"port":(tp.Integer(), "Port", 42010),
|
||||||
|
},
|
||||||
|
"Technical":{
|
||||||
|
"cache_expire_positive":(tp.Integer(), "Image Cache Expiration", 300, "Days until images are refetched"),
|
||||||
|
"cache_expire_negative":(tp.Integer(), "Image Cache Negative Expiration", 30, "Days until failed image fetches are reattempted"),
|
||||||
|
"use_db_cache":(tp.Boolean(), "Use DB Cache", True),
|
||||||
|
"cache_database_short":(tp.Boolean(), "Use volatile Database Cache", True),
|
||||||
|
"cache_database_perm":(tp.Boolean(), "Use permanent Database Cache", True),
|
||||||
|
"db_cache_entries":(tp.Integer(), "Maximal Cache entries", 10000),
|
||||||
|
"db_max_memory":(tp.Integer(max=100,min=20), "RAM Percentage Theshold", 75, "Maximal percentage of RAM that should be used by whole system before Maloja discards cache entries. Use a higher number if your Maloja runs on a dedicated instance (e.g. a container)")
|
||||||
|
},
|
||||||
|
"Fluff":{
|
||||||
|
"scrobbles_gold":(tp.Integer(), "Scrobbles for Gold", 250, "How many scrobbles a track needs to be considered 'Gold' status"),
|
||||||
|
"scrobbles_platinum":(tp.Integer(), "Scrobbles for Platinum", 500, "How many scrobbles a track needs to be considered 'Platinum' status"),
|
||||||
|
"scrobbles_diamond":(tp.Integer(), "Scrobbles for Diamond", 1000, "How many scrobbles a track needs to be considered 'Diamond' status"),
|
||||||
|
"name":(tp.String(), "Name", "Generic Maloja User")
|
||||||
|
},
|
||||||
|
"Third Party Services":{
|
||||||
|
"metadata_providers":(tp.List(tp.String()), "Metadata Providers", ['lastfm','spotify','deezer','musicbrainz'], "Which metadata providers should be used in what order. Musicbrainz is rate-limited and should not be used first."),
|
||||||
|
"scrobble_lastfm":(tp.Boolean(), "Proxy-Scrobble to Last.fm", False),
|
||||||
|
"lastfm_api_key":(tp.String(), "Last.fm API Key", None),
|
||||||
|
"lastfm_api_secret":(tp.String(), "Last.fm API Secret", None),
|
||||||
|
"spotify_api_id":(tp.String(), "Spotify API ID", None),
|
||||||
|
"spotify_api_secret":(tp.String(), "Spotify API Secret", None),
|
||||||
|
"lastfm_api_key":(tp.String(), "Last.fm API Key", None),
|
||||||
|
"audiodb_api_key":(tp.String(), "TheAudioDB API Key", None),
|
||||||
|
"track_search_provider":(tp.String(), "Track Search Provider", None),
|
||||||
|
"send_stats":(tp.Boolean(), "Send Statistics", None),
|
||||||
|
|
||||||
|
},
|
||||||
|
"Database":{
|
||||||
|
"invalid_artists":(tp.Set(tp.String()), "Invalid Artists", ["[Unknown Artist]","Unknown Artist","Spotify"], "Artists that should be discarded immediately"),
|
||||||
|
"remove_from_title":(tp.Set(tp.String()), "Remove from Title", ["(Original Mix)","(Radio Edit)","(Album Version)","(Explicit Version)","(Bonus Track)"], "Phrases that should be removed from song titles"),
|
||||||
|
"delimiters_feat":(tp.Set(tp.String()), "Featuring Delimiters", ["ft.","ft","feat.","feat","featuring","Ft.","Ft","Feat.","Feat","Featuring"], "Delimiters used for extra artists, even when in the title field"),
|
||||||
|
"delimiters_informal":(tp.Set(tp.String()), "Informal Delimiters", ["vs.","vs","&"], "Delimiters in informal artist strings with spaces expected around them"),
|
||||||
|
"delimiters_formal":(tp.Set(tp.String()), "Formal Delimiters", [";","/"], "Delimiters used to tag multiple artists when only one tag field is available")
|
||||||
|
},
|
||||||
|
"Web Interface":{
|
||||||
|
"default_range_charts_artists":(tp.Choice({'alltime':'All Time','year':'Year','month':"Month",'week':'Week'}), "Default Range Artist Charts", "year"),
|
||||||
|
"default_range_charts_tracks":(tp.Choice({'alltime':'All Time','year':'Year','month':"Month",'week':'Week'}), "Default Range Track Charts", "year"),
|
||||||
|
"default_step_pulse":(tp.Choice({'year':'Year','month':"Month",'week':'Week','day':'Day'}), "Default Pulse Step", "month"),
|
||||||
|
"charts_display_tiles":(tp.Boolean(), "Display Chart Tiles", False),
|
||||||
|
"discourage_cpu_heavy_stats":(tp.Boolean(), "Discourage CPU-heavy stats", False, "Prevent visitors from mindlessly clicking on CPU-heavy options. Does not actually disable them for malicious actors!"),
|
||||||
|
"use_local_images":(tp.Boolean(), "Use Local Images", True),
|
||||||
|
"local_image_rotate":(tp.Integer(), "Local Image Rotate", 3600),
|
||||||
|
"timezone":(tp.Integer(), "UTC Offset", 0),
|
||||||
|
"time_format":(tp.String(), "Time Format", "%d. %b %Y %I:%M %p")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
configfile=newsettingsfile,
|
||||||
|
save_endpoint="/apis/mlj_1/settings",
|
||||||
|
env_prefix="MALOJA_"
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
malojaconfig["DIRECTORY_CONFIG"] = maloja_dir_config
|
||||||
|
|
||||||
|
|
||||||
|
### STEP 3 - check all possible folders for files (old installation)
|
||||||
|
|
||||||
|
directory_info = {
|
||||||
|
"cache":{
|
||||||
|
"sentinel":"dummy",
|
||||||
|
"possible_folders":[
|
||||||
|
"/var/cache/maloja",
|
||||||
|
"$HOME/.local/share/maloja/cache"
|
||||||
|
],
|
||||||
|
"setting":"directory_cache"
|
||||||
|
},
|
||||||
|
"state":{
|
||||||
|
"sentinel":"scrobbles",
|
||||||
|
"possible_folders":[
|
||||||
|
"/var/lib/maloja",
|
||||||
|
"$HOME/.local/share/maloja"
|
||||||
|
],
|
||||||
|
"setting":"directory_state"
|
||||||
|
},
|
||||||
|
"logs":{
|
||||||
|
"sentinel":"dbfix",
|
||||||
|
"possible_folders":[
|
||||||
|
"/var/log/maloja",
|
||||||
|
"$HOME/.local/share/maloja/logs"
|
||||||
|
],
|
||||||
|
"setting":"directory_logs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for datatype in directory_info:
|
||||||
|
info = directory_info[datatype]
|
||||||
|
|
||||||
|
# check if we already have a user-specified setting
|
||||||
|
# default obv shouldn't count here, so use get_specified
|
||||||
|
if malojaconfig.get_specified(info['setting']) is None and malojaconfig.get_specified('DATA_DIRECTORY') is None:
|
||||||
|
# check each possible folder if its used
|
||||||
|
for p in info['possible_folders']:
|
||||||
|
if os.path.exists(pthj(p,info['sentinel'])):
|
||||||
|
print(p,"has been determined as maloja's folder for",datatype)
|
||||||
|
malojaconfig[info['setting']] = p
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print("Could not find previous",datatype,"folder")
|
||||||
|
# check which one we can use
|
||||||
|
for p in info['possible_folders']:
|
||||||
|
if is_dir_usable(p):
|
||||||
|
print(p,"has been selected as maloja's folder for",datatype)
|
||||||
|
malojaconfig[info['setting']] = p
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print("No folder can be used for",datatype)
|
||||||
|
print("This should not happen!")
|
||||||
|
|
||||||
|
if malojaconfig['DATA_DIRECTORY'] is None:
|
||||||
|
top_dirs = {
|
||||||
|
"config":malojaconfig['DIRECTORY_CONFIG'],
|
||||||
|
"state":malojaconfig['DIRECTORY_STATE'],
|
||||||
|
"cache":malojaconfig['DIRECTORY_CACHE'],
|
||||||
|
"logs":malojaconfig['DIRECTORY_LOGS'],
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
top_dirs = {
|
||||||
|
"config":malojaconfig['DATA_DIRECTORY'],
|
||||||
|
"state":malojaconfig['DATA_DIRECTORY'],
|
||||||
|
"cache":pthj(malojaconfig['DATA_DIRECTORY'],"cache"),
|
||||||
|
"logs":pthj(malojaconfig['DATA_DIRECTORY'],"logs"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
data_directories = {
|
data_directories = {
|
||||||
"auth":pthj(dir_settings['state'],"auth"),
|
"auth":pthj(top_dirs['state'],"auth"),
|
||||||
"backups":pthj(dir_settings['state'],"backups"),
|
"backups":pthj(top_dirs['state'],"backups"),
|
||||||
"images":pthj(dir_settings['state'],"images"),
|
"images":pthj(top_dirs['state'],"images"),
|
||||||
"scrobbles":pthj(dir_settings['state'],"scrobbles"),
|
"scrobbles":pthj(top_dirs['state'],"scrobbles"),
|
||||||
"rules":pthj(dir_settings['config'],"rules"),
|
"rules":pthj(top_dirs['config'],"rules"),
|
||||||
"clients":pthj(dir_settings['config'],"clients"),
|
"clients":pthj(top_dirs['config'],"clients"),
|
||||||
"settings":pthj(dir_settings['config'],"settings"),
|
"settings":pthj(top_dirs['config']),
|
||||||
"css":pthj(dir_settings['config'],"custom_css"),
|
"css":pthj(top_dirs['config'],"custom_css"),
|
||||||
"logs":pthj(dir_settings['logs']),
|
"logs":pthj(top_dirs['logs']),
|
||||||
"cache":pthj(dir_settings['cache']),
|
"cache":pthj(top_dirs['cache']),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -144,13 +257,6 @@ data_dir = {
|
|||||||
from doreah import config
|
from doreah import config
|
||||||
|
|
||||||
config(
|
config(
|
||||||
settings={
|
|
||||||
"files":[
|
|
||||||
data_dir['settings']("default.ini"),
|
|
||||||
data_dir['settings']("settings.ini")
|
|
||||||
],
|
|
||||||
"environ_prefix":"MALOJA_"
|
|
||||||
},
|
|
||||||
caching={
|
caching={
|
||||||
"folder": data_dir['cache']()
|
"folder": data_dir['cache']()
|
||||||
},
|
},
|
||||||
@ -159,119 +265,14 @@ config(
|
|||||||
"cookieprefix":"maloja",
|
"cookieprefix":"maloja",
|
||||||
"stylesheets":["/style.css"],
|
"stylesheets":["/style.css"],
|
||||||
"dbfile":data_dir['auth']("auth.ddb")
|
"dbfile":data_dir['auth']("auth.ddb")
|
||||||
}
|
},
|
||||||
)
|
|
||||||
|
|
||||||
# because we loaded a doreah module already before setting the config, we need to to that manually
|
|
||||||
settingsconfig._readpreconfig()
|
|
||||||
|
|
||||||
config(
|
|
||||||
logging={
|
logging={
|
||||||
"logfolder": data_dir['logs']() if get_settings("LOGGING") else None
|
"logfolder": data_dir['logs']() if malojaconfig["LOGGING"] else None
|
||||||
},
|
},
|
||||||
regular={
|
regular={
|
||||||
"autostart": False,
|
"autostart": False,
|
||||||
"offset": get_settings("TIMEZONE")
|
"offset": malojaconfig["TIMEZONE"]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
settingsconfig._readpreconfig()
|
settingsconfig._readpreconfig()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# thumbor
|
|
||||||
|
|
||||||
THUMBOR_SERVER, THUMBOR_SECRET = get_settings("THUMBOR_SERVER","THUMBOR_SECRET")
|
|
||||||
try:
|
|
||||||
USE_THUMBOR = THUMBOR_SERVER is not None and THUMBOR_SECRET is not None
|
|
||||||
if USE_THUMBOR:
|
|
||||||
from libthumbor import CryptoURL
|
|
||||||
THUMBOR_GENERATOR = CryptoURL(key=THUMBOR_SECRET)
|
|
||||||
OWNURL = get_settings("PUBLIC_URL")
|
|
||||||
assert OWNURL is not None
|
|
||||||
except:
|
|
||||||
USE_THUMBOR = False
|
|
||||||
log("Thumbor could not be initialized. Is libthumbor installed?")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# new config
|
|
||||||
|
|
||||||
|
|
||||||
malojaconfig = Configuration(
|
|
||||||
settings={
|
|
||||||
"Setup":{
|
|
||||||
"data_directory":(tp.String(), "Data Directory", None, "Folder for all user data. Overwrites all choices for specific directories."),
|
|
||||||
"directory_config":(tp.String(), "Config Directory", "/etc/maloja", "Folder for config data. Only applied when global data directory is not set."),
|
|
||||||
"directory_state":(tp.String(), "State Directory", "/var/lib/maloja", "Folder for state data. Only applied when global data directory is not set."),
|
|
||||||
"directory_logs":(tp.String(), "Log Directory", "/var/log/maloja", "Folder for log data. Only applied when global data directory is not set."),
|
|
||||||
"directory_cache":(tp.String(), "Cache Directory", "/var/cache/maloja", "Folder for cache data. Only applied when global data directory is not set."),
|
|
||||||
"skip_setup":(tp.Boolean(), "Skip Setup", False, "Make server setup process non-interactive. Vital for Docker."),
|
|
||||||
"force_password":(tp.String(), "Force Password", None, "On startup, overwrite admin password with this one. This should usually only be done via environment variable in Docker."),
|
|
||||||
"clean_output":(tp.Boolean(), "Avoid Mutable Console Output", False, "Use if console output will be redirected e.g. to a web interface.")
|
|
||||||
},
|
|
||||||
"Debug":{
|
|
||||||
"logging":(tp.Boolean(), "Enable Logging", True),
|
|
||||||
"dev_mode":(tp.Boolean(), "Enable developer mode", False),
|
|
||||||
},
|
|
||||||
"Network":{
|
|
||||||
"host":(tp.String(), "Host", "::", "Host for your server - most likely :: for IPv6 or 0.0.0.0 for IPv4"),
|
|
||||||
"port":(tp.Integer(), "Port", 42010),
|
|
||||||
},
|
|
||||||
"Technical":{
|
|
||||||
"cache_expire_positive":(tp.Integer(), "Image Cache Expiration", 300, "Days until images are refetched"),
|
|
||||||
"cache_expire_negative":(tp.Integer(), "Image Cache Negative Expiration", 30, "Days until failed image fetches are reattempted"),
|
|
||||||
"use_db_cache":(tp.Boolean(), "Use DB Cache", True),
|
|
||||||
"cache_database_short":(tp.Boolean(), "Use volatile Database Cache", True),
|
|
||||||
"cache_database_perm":(tp.Boolean(), "Use permanent Database Cache", True),
|
|
||||||
"db_cache_entries":(tp.Integer(), "Maximal Cache entries", 10000),
|
|
||||||
"db_max_memory":(tp.Integer(max=100,min=20), "RAM Percentage Theshold", 75, "Maximal percentage of RAM that should be used by whole system before Maloja discards cache entries. Use a higher number if your Maloja runs on a dedicated instance (e.g. a container)")
|
|
||||||
},
|
|
||||||
"Fluff":{
|
|
||||||
"scrobbles_gold":(tp.Integer(), "Scrobbles for Gold", 250, "How many scrobbles a track needs to be considered 'Gold' status"),
|
|
||||||
"scrobbles_platinum":(tp.Integer(), "Scrobbles for Platinum", 500, "How many scrobbles a track needs to be considered 'Platinum' status"),
|
|
||||||
"scrobbles_diamond":(tp.Integer(), "Scrobbles for Diamond", 1000, "How many scrobbles a track needs to be considered 'Diamond' status"),
|
|
||||||
"name":(tp.String(), "Name", "Generic Maloja User")
|
|
||||||
},
|
|
||||||
"Third Party Services":{
|
|
||||||
"metadata_providers":(tp.List(tp.String()), "Metadata Providers", ['lastfm','spotify','deezer','musicbrainz'], "Which metadata providers should be used in what order. Musicbrainz is rate-limited and should not be used first."),
|
|
||||||
"scrobble_lastfm":(tp.Boolean(), "Proxy-Scrobble to Last.fm", False),
|
|
||||||
"lastfm_api_key":(tp.String(), "Last.fm API Key", None),
|
|
||||||
"lastfm_api_secret":(tp.String(), "Last.fm API Secret", None),
|
|
||||||
"spotify_api_id":(tp.String(), "Spotify API ID", None),
|
|
||||||
"spotify_api_secret":(tp.String(), "Spotify API Secret", None),
|
|
||||||
"lastfm_api_key":(tp.String(), "Last.fm API Key", None),
|
|
||||||
"audiodb_api_key":(tp.String(), "TheAudioDB API Key", None),
|
|
||||||
"track_search_provider":(tp.String(), "Track Search Provider", None),
|
|
||||||
"send_stats":(tp.Boolean(), "Send Statistics", None),
|
|
||||||
|
|
||||||
},
|
|
||||||
"Database":{
|
|
||||||
"invalid_artists":(tp.Set(tp.String()), "Invalid Artists", ["[Unknown Artist]","Unknown Artist","Spotify"], "Artists that should be discarded immediately"),
|
|
||||||
"remove_from_title":(tp.Set(tp.String()), "Remove from Title", ["(Original Mix)","(Radio Edit)","(Album Version)","(Explicit Version)","(Bonus Track)"], "Phrases that should be removed from song titles"),
|
|
||||||
"delimiters_feat":(tp.Set(tp.String()), "Featuring Delimiters", ["ft.","ft","feat.","feat","featuring","Ft.","Ft","Feat.","Feat","Featuring"], "Delimiters used for extra artists, even when in the title field"),
|
|
||||||
"delimiters_informal":(tp.Set(tp.String()), "Informal Delimiters", ["vs.","vs","&"], "Delimiters in informal artist strings with spaces expected around them"),
|
|
||||||
"delimiters_formal":(tp.Set(tp.String()), "Formal Delimiters", [";","/"], "Delimiters used to tag multiple artists when only one tag field is available")
|
|
||||||
},
|
|
||||||
"Web Interface":{
|
|
||||||
"default_range_charts_artists":(tp.Choice({'alltime':'All Time','year':'Year','month':"Month",'week':'Week'}), "Default Range Artist Charts", "year"),
|
|
||||||
"default_range_charts_tracks":(tp.Choice({'alltime':'All Time','year':'Year','month':"Month",'week':'Week'}), "Default Range Track Charts", "year"),
|
|
||||||
"default_step_pulse":(tp.Choice({'year':'Year','month':"Month",'week':'Week','day':'Day'}), "Default Pulse Step", "month"),
|
|
||||||
"charts_display_tiles":(tp.Boolean(), "Display Chart Tiles", False),
|
|
||||||
"discourage_cpu_heavy_stats":(tp.Boolean(), "Discourage CPU-heavy stats", False, "Prevent visitors from mindlessly clicking on CPU-heavy options. Does not actually disable them for malicious actors!"),
|
|
||||||
"use_local_images":(tp.Boolean(), "Use Local Images", True),
|
|
||||||
"local_image_rotate":(tp.Integer(), "Local Image Rotate", 3600),
|
|
||||||
"timezone":(tp.Integer(), "UTC Offset", 0),
|
|
||||||
"time_format":(tp.String(), "Time Format", "%d. %b %Y %I:%M %p")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
configfile=data_dir['settings']("settings.ini"),
|
|
||||||
save_endpoint="/apis/mlj_1/settings",
|
|
||||||
env_prefix="MALOJA_"
|
|
||||||
|
|
||||||
)
|
|
||||||
|
@ -43,7 +43,7 @@ def setup():
|
|||||||
key = prompt("",types=(str,),default=False,skip=SKIP)
|
key = prompt("",types=(str,),default=False,skip=SKIP)
|
||||||
malojaconfig[k] = key
|
malojaconfig[k] = key
|
||||||
else:
|
else:
|
||||||
print("\t" + col['green'](apikeys[k]) + " found.")
|
print("\t" + col['lawngreen'](apikeys[k]) + " found.")
|
||||||
|
|
||||||
|
|
||||||
# OWN API KEY
|
# OWN API KEY
|
||||||
@ -56,7 +56,6 @@ def setup():
|
|||||||
keyfile.write(key + "\t" + "Default Generated Key")
|
keyfile.write(key + "\t" + "Default Generated Key")
|
||||||
|
|
||||||
# PASSWORD
|
# PASSWORD
|
||||||
defaultpassword = malojaconfig["DEFAULT_PASSWORD"]
|
|
||||||
forcepassword = malojaconfig["FORCE_PASSWORD"]
|
forcepassword = malojaconfig["FORCE_PASSWORD"]
|
||||||
# this is mainly meant for docker, supply password via environment variable
|
# this is mainly meant for docker, supply password via environment variable
|
||||||
|
|
||||||
@ -66,23 +65,12 @@ def setup():
|
|||||||
print("Password has been set.")
|
print("Password has been set.")
|
||||||
elif auth.defaultuser.checkpw("admin"):
|
elif auth.defaultuser.checkpw("admin"):
|
||||||
# if the actual pw is admin, it means we've never set this up properly (eg first start after update)
|
# if the actual pw is admin, it means we've never set this up properly (eg first start after update)
|
||||||
if defaultpassword is None:
|
newpw = prompt("Please set a password for web backend access. Leave this empty to generate a random password.",skip=SKIP,secret=True)
|
||||||
# non-docker installation or user didn't set environment variable
|
if newpw is None:
|
||||||
defaultpassword = randomstring(32)
|
newpw = randomstring(32)
|
||||||
newpw = prompt("Please set a password for web backend access. Leave this empty to generate a random password.",skip=SKIP,secret=True)
|
print("Generated password:",newpw)
|
||||||
if newpw is None:
|
|
||||||
newpw = defaultpassword
|
|
||||||
print("Generated password:",newpw)
|
|
||||||
else:
|
|
||||||
# docker installation (or settings file, but don't do that)
|
|
||||||
# we still 'ask' the user to set one, but for docker this will be skipped
|
|
||||||
newpw = prompt("Please set a password for web backend access. Leave this empty to use the default password.",skip=SKIP,default=defaultpassword,secret=True)
|
|
||||||
auth.defaultuser.setpw(newpw)
|
auth.defaultuser.setpw(newpw)
|
||||||
if malojaconfig["NAME"] == "Generic Maloja User":
|
|
||||||
name = prompt("Please enter your name. This will be displayed e.g. when comparing your charts to another user. Leave this empty if you would not like to specify a name right now.",default="Maloja User",skip=SKIP)
|
|
||||||
malojaconfig["NAME"] = name
|
|
||||||
# setting this as an actual setting instead of leaving the default fallback
|
|
||||||
# so we know not to ask again
|
|
||||||
|
|
||||||
if malojaconfig["SEND_STATS"] is None:
|
if malojaconfig["SEND_STATS"] is None:
|
||||||
answer = ask("I would like to know how many people use Maloja. Would it be okay to send a daily ping to my server (this contains no data that isn't accessible via your web interface already)?",default=True,skip=SKIP)
|
answer = ask("I would like to know how many people use Maloja. Would it be okay to send a daily ping to my server (this contains no data that isn't accessible via your web interface already)?",default=True,skip=SKIP)
|
||||||
|
Loading…
Reference in New Issue
Block a user