From 09e484021cd3a89226cfbfffe16cd8349cd7d147 Mon Sep 17 00:00:00 2001 From: krateng Date: Sun, 12 Dec 2021 18:43:24 +0100 Subject: [PATCH 01/18] Began work on new settings implementation --- maloja/globalconf.py | 78 ++++++++++++++++++++++++++ maloja/server.py | 2 + maloja/web/jinja/abstracts/admin.jinja | 7 ++- maloja/web/jinja/admin_settings.jinja | 8 +++ 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 maloja/web/jinja/admin_settings.jinja diff --git a/maloja/globalconf.py b/maloja/globalconf.py index 191fbe4..0a85537 100644 --- a/maloja/globalconf.py +++ b/maloja/globalconf.py @@ -1,6 +1,8 @@ import os from doreah.settings import get_settings from doreah.settings import config as settingsconfig +from doreah.configuration import Configuration +from doreah.configuration import types as tp pthj = os.path.join @@ -190,3 +192,79 @@ try: except: USE_THUMBOR = False log("Thumbor could not be initialized. Is libthumbor installed?") + + + + + + + + +# new config + + +malojaconfig = Configuration( + settings={ + "Setup":{ + "directory_state":(tp.String(), "State Directory", "/var/lib/maloja"), + "directory_logs":(tp.String(), "Log Directory", "/var/log/maloja"), + "directory_cache":(tp.String(), "Cache Directory", "/var/cache/maloja"), + "skip_setup":(tp.Boolean(), "Skip Setup", False), + "force_password":(tp.String(), "Force Password", None), + "clean_output":(tp.Boolean(), "Avoid Mutable Console Output", False) + }, + "Debug":{ + "logging":(tp.Boolean(), "Enable Logging", True), + "dev_mode":(tp.Boolean(), "Enable developer mode", False), + }, + "Network":{ + "host":(tp.String(), "Host", "::"), + "port":(tp.Integer(), "Port", 42010), + }, + "Technical":{ + "cache_expire_positive":(tp.Integer(), "Days until images are refetched", 300), + "cache_expire_negative":(tp.Integer(), "Days until failed image fetches are reattempted", 30), + "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(), "RAM Percentage Theshold", 75) + }, + "Fluff":{ + "scrobbles_gold":(tp.Integer(), "Scrobbles for Gold", 250), + "scrobbles_platinum":(tp.Integer(), "Scrobbles for Platinum", 500), + "scrobbles_diamond":(tp.Integer(), "Scrobbles for Diamond", 1000), + "name":(tp.String(), "Name", "Maloja User") + }, + "Third Party Services":{ + "metadata_providers":(tp.List(tp.String()), "Metadata Providers", ['lastfm','spotify','deezer','musicbrainz']), + "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), + "track_search_provider":(tp.String(), "Track Search Provider", None) + + }, + "Database":{ + "invalid_artists":(tp.Set(tp.String()), "Invalid Artists", ["[Unknown Artist]","Unknown Artist","Spotify"]), + "remove_from_title":(tp.Set(tp.String()), "Remove from Title", ["(Original Mix)","(Radio Edit)","(Album Version)","(Explicit Version)","(Bonus Track)"]), + "delimiters_feat":(tp.Set(tp.String()), "Delimiters featuring", ["ft.","ft","feat.","feat","featuring","Ft.","Ft","Feat.","Feat","Featuring"]), + "delimiters_informal":(tp.Set(tp.String()), "Informal Delimiters", ["vs.","vs","&"]), + "delimiters_formal":(tp.Set(tp.String()), "Formal Delimiters", [";","/"]) + }, + "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), + "use_local_images":(tp.Boolean(), "Use Local Images", True), + "local_image_rotate":(tp.Integer(), "Use Local Images", 3600), + "timezone":(tp.Integer(), "UTC Offset", 0), + "time_format":(tp.String(), "Time Format", "%d. %b %Y %I:%M %p") + } + } + + ) diff --git a/maloja/server.py b/maloja/server.py index e89bf53..6559a88 100644 --- a/maloja/server.py +++ b/maloja/server.py @@ -17,6 +17,7 @@ from . import malojauri from .utilities import resolveImage from .malojauri import uri_to_internal, remove_identical, compose_querystring from . import globalconf +from .globalconf import malojaconfig from .jinjaenv.context import jinja_environment from jinja2.exceptions import TemplateNotFound # doreah toolkit @@ -247,6 +248,7 @@ def static_html(name): LOCAL_CONTEXT = { "adminmode":adminmode, + "config":malojaconfig, "apikey":request.cookies.get("apikey") if adminmode else None, "_urikeys":keys, #temporary! } diff --git a/maloja/web/jinja/abstracts/admin.jinja b/maloja/web/jinja/abstracts/admin.jinja index 76c95ad..01270ca 100644 --- a/maloja/web/jinja/abstracts/admin.jinja +++ b/maloja/web/jinja/abstracts/admin.jinja @@ -35,7 +35,12 @@ Database Maintenance {% else %} Database Maintenance - {% endif %} + {% endif %}

diff --git a/maloja/web/jinja/admin_settings.jinja b/maloja/web/jinja/admin_settings.jinja new file mode 100644 index 0000000..2b6b53e --- /dev/null +++ b/maloja/web/jinja/admin_settings.jinja @@ -0,0 +1,8 @@ +{% set page ='admin_settings' %} +{% extends "abstracts/admin.jinja" %} +{% block title %}Maloja - Settings{% endblock %} + + +{% block maincontent %} +{{ config.html() }} +{% endblock %} From e597ba8504c1e36e4fe97e45a9962fd2117b805b Mon Sep 17 00:00:00 2001 From: krateng Date: Tue, 14 Dec 2021 21:19:15 +0100 Subject: [PATCH 02/18] More work on new settings --- maloja/apis/native_v1.py | 10 +++++++++- maloja/globalconf.py | 10 ++++++---- maloja/server.py | 6 ++++-- maloja/web/jinja/abstracts/admin.jinja | 4 ++-- maloja/web/jinja/abstracts/base.jinja | 4 ++-- 5 files changed, 23 insertions(+), 11 deletions(-) diff --git a/maloja/apis/native_v1.py b/maloja/apis/native_v1.py index 7cd66f2..2a53876 100644 --- a/maloja/apis/native_v1.py +++ b/maloja/apis/native_v1.py @@ -61,7 +61,7 @@ def get_scrobbles_external(**keys): offset = (k_amount.get('page') * k_amount.get('perpage')) if k_amount.get('perpage') is not math.inf else 0 result = result[offset:] if k_amount.get('perpage') is not math.inf: result = result[:k_amount.get('perpage')] - + return {"list":result} @@ -326,3 +326,11 @@ def add_picture(b64,artist:Multi=[],title=None): def newrule(**keys): tsv.add_entry(data_dir['rules']("webmade.tsv"),[k for k in keys]) #addEntry("rules/webmade.tsv",[k for k in keys]) + + +@api.post("settings") +@authenticated_api +def settings(**keys): + from .. import globalconf + print(keys) + globalconf.malojaconfig.update(keys) diff --git a/maloja/globalconf.py b/maloja/globalconf.py index 0a85537..8274f7b 100644 --- a/maloja/globalconf.py +++ b/maloja/globalconf.py @@ -228,7 +228,7 @@ malojaconfig = Configuration( "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(), "RAM Percentage Theshold", 75) + "db_max_memory":(tp.Integer(max=100,min=20), "RAM Percentage Theshold", 75) }, "Fluff":{ "scrobbles_gold":(tp.Integer(), "Scrobbles for Gold", 250), @@ -250,7 +250,7 @@ malojaconfig = Configuration( "Database":{ "invalid_artists":(tp.Set(tp.String()), "Invalid Artists", ["[Unknown Artist]","Unknown Artist","Spotify"]), "remove_from_title":(tp.Set(tp.String()), "Remove from Title", ["(Original Mix)","(Radio Edit)","(Album Version)","(Explicit Version)","(Bonus Track)"]), - "delimiters_feat":(tp.Set(tp.String()), "Delimiters featuring", ["ft.","ft","feat.","feat","featuring","Ft.","Ft","Feat.","Feat","Featuring"]), + "delimiters_feat":(tp.Set(tp.String()), "Featuring Delimiters", ["ft.","ft","feat.","feat","featuring","Ft.","Ft","Feat.","Feat","Featuring"]), "delimiters_informal":(tp.Set(tp.String()), "Informal Delimiters", ["vs.","vs","&"]), "delimiters_formal":(tp.Set(tp.String()), "Formal Delimiters", [";","/"]) }, @@ -261,10 +261,12 @@ malojaconfig = Configuration( "charts_display_tiles":(tp.Boolean(), "Display Chart Tiles", False), "discourage_cpu_heavy_stats":(tp.Boolean(), "Discourage CPU-heavy stats", False), "use_local_images":(tp.Boolean(), "Use Local Images", True), - "local_image_rotate":(tp.Integer(), "Use Local Images", 3600), + "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" ) diff --git a/maloja/server.py b/maloja/server.py index 6559a88..85214d7 100644 --- a/maloja/server.py +++ b/maloja/server.py @@ -88,8 +88,10 @@ css = generate_css() ##### def clean_html(inp): - if settings.get_settings("DEV_MODE"): return inp - else: return html_minify(inp) + return inp + + #if settings.get_settings("DEV_MODE"): return inp + #else: return html_minify(inp) diff --git a/maloja/web/jinja/abstracts/admin.jinja b/maloja/web/jinja/abstracts/admin.jinja index 01270ca..2098ea3 100644 --- a/maloja/web/jinja/abstracts/admin.jinja +++ b/maloja/web/jinja/abstracts/admin.jinja @@ -35,12 +35,12 @@ Database Maintenance {% else %} Database Maintenance - {% endif %} + {% endif %}

diff --git a/maloja/web/jinja/abstracts/base.jinja b/maloja/web/jinja/abstracts/base.jinja index 255e93e..2ea6362 100644 --- a/maloja/web/jinja/abstracts/base.jinja +++ b/maloja/web/jinja/abstracts/base.jinja @@ -54,7 +54,7 @@ - +
Artists @@ -64,7 +64,7 @@
- +
From b39e2b889a59fc9f07a4442d11846e7fb0d24858 Mon Sep 17 00:00:00 2001 From: krateng Date: Sun, 19 Dec 2021 21:04:43 +0100 Subject: [PATCH 03/18] Added description for some settings --- maloja/apis/native_v1.py | 5 +++-- maloja/globalconf.py | 16 +++++++++------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/maloja/apis/native_v1.py b/maloja/apis/native_v1.py index 2a53876..8844d7e 100644 --- a/maloja/apis/native_v1.py +++ b/maloja/apis/native_v1.py @@ -330,7 +330,8 @@ def newrule(**keys): @api.post("settings") @authenticated_api -def settings(**keys): +def set_settings(**keys): from .. import globalconf - print(keys) + from pprint import pprint + pprint(keys) globalconf.malojaconfig.update(keys) diff --git a/maloja/globalconf.py b/maloja/globalconf.py index 8274f7b..9577397 100644 --- a/maloja/globalconf.py +++ b/maloja/globalconf.py @@ -206,19 +206,21 @@ except: malojaconfig = Configuration( settings={ "Setup":{ - "directory_state":(tp.String(), "State Directory", "/var/lib/maloja"), - "directory_logs":(tp.String(), "Log Directory", "/var/log/maloja"), - "directory_cache":(tp.String(), "Cache Directory", "/var/cache/maloja"), - "skip_setup":(tp.Boolean(), "Skip Setup", False), - "force_password":(tp.String(), "Force Password", None), - "clean_output":(tp.Boolean(), "Avoid Mutable Console Output", False) + "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"), + "force_password":(tp.String(), "Force Password", None, "On startup, overwrite admin password with this one"), + "clean_output":(tp.Boolean(), "Avoid Mutable Console Output", False, "No console output that will cause problems when piped to other outputs") }, "Debug":{ "logging":(tp.Boolean(), "Enable Logging", True), "dev_mode":(tp.Boolean(), "Enable developer mode", False), }, "Network":{ - "host":(tp.String(), "Host", "::"), + "host":(tp.String(), "Host", "::", "Use :: for default IPv6, 0.0.0.0 for default IPv4"), "port":(tp.Integer(), "Port", 42010), }, "Technical":{ From 4186171b8fff984bc189b8cfaa2816d8a26c50fb Mon Sep 17 00:00:00 2001 From: krateng Date: Sun, 19 Dec 2021 21:10:55 +0100 Subject: [PATCH 04/18] Replaced settings calls --- maloja/apis/listenbrainz.py | 4 ++-- maloja/apis/native_v1.py | 4 ++-- maloja/cleanup.py | 14 +++++++------- maloja/database.py | 16 ++++++++-------- maloja/malojatime.py | 7 ++++--- maloja/proccontrol/control.py | 2 +- maloja/proccontrol/setup.py | 24 ++++++++++++------------ maloja/proccontrol/supervisor.py | 4 ++-- maloja/server.py | 10 +++++----- maloja/thirdparty/__init__.py | 12 ++++++------ maloja/utilities/images.py | 10 +++++----- maloja/utilities/maintenance.py | 6 +++--- 12 files changed, 57 insertions(+), 56 deletions(-) diff --git a/maloja/apis/listenbrainz.py b/maloja/apis/listenbrainz.py index 9948148..80f8ba1 100644 --- a/maloja/apis/listenbrainz.py +++ b/maloja/apis/listenbrainz.py @@ -3,7 +3,7 @@ from ._exceptions import * from .. import database import datetime -from doreah.settings import get_settings +from .globalconf import malojaconfig class Listenbrainz(APIHandler): @@ -72,7 +72,7 @@ class Listenbrainz(APIHandler): if token not in database.allAPIkeys(): raise InvalidAuthException() else: - return 200,{"code":200,"message":"Token valid.","valid":True,"user_name":get_settings("NAME") or 'Maloja User'} + return 200,{"code":200,"message":"Token valid.","valid":True,"user_name":malojaconfig["NAME"]} def get_token_from_request_keys(self,keys): if 'token' in keys: diff --git a/maloja/apis/native_v1.py b/maloja/apis/native_v1.py index 8844d7e..a9899a8 100644 --- a/maloja/apis/native_v1.py +++ b/maloja/apis/native_v1.py @@ -1,5 +1,5 @@ from ..database import * -from doreah import settings +from ..globalconf import malojaconfig from ..__pkginfo__ import version from ..malojauri import uri_to_internal from .. import utilities @@ -41,7 +41,7 @@ def server_info(): response.set_header("Content-Type","application/json") return { - "name":settings.get_settings("NAME"), + "name":malojaconfig["NAME"], "version":version, "versionstring":".".join(str(n) for n in version), "db_status":dbstatus diff --git a/maloja/cleanup.py b/maloja/cleanup.py index 6b2e238..589a591 100644 --- a/maloja/cleanup.py +++ b/maloja/cleanup.py @@ -1,7 +1,7 @@ import re #from . import utilities -from doreah import tsv, settings -from .globalconf import data_dir +from doreah import tsv +from .globalconf import data_dir, malojaconfig import pkg_resources # need to do this as a class so it can retain loaded settings from file @@ -62,13 +62,13 @@ class CleanerAgent: #Delimiters used for extra artists, even when in the title field #delimiters_feat = ["ft.","ft","feat.","feat","featuring","Ft.","Ft","Feat.","Feat","Featuring"] - delimiters_feat = settings.get_settings("DELIMITERS_FEAT") + delimiters_feat = malojaconfig["DELIMITERS_FEAT"] #Delimiters in informal artist strings, spaces expected around them #delimiters = ["vs.","vs","&"] - delimiters = settings.get_settings("DELIMITERS_INFORMAL") + delimiters = malojaconfig["DELIMITERS_FEAT"] #Delimiters used specifically to tag multiple artists when only one tag field is available, no spaces used #delimiters_formal = ["; ",";","/"] - delimiters_formal = settings.get_settings("DELIMITERS_FORMAL") + delimiters_formal = malojaconfig["DELIMITERS_FEAT"] def parseArtists(self,a): @@ -76,7 +76,7 @@ class CleanerAgent: res = [self.parseArtists(art) for art in a] return [a for group in res for a in group] - if a.strip() in settings.get_settings("INVALID_ARTISTS"): + if a.strip() in malojaconfig["DELIMITERS_FEAT"]: return [] if a.strip().lower() in self.rules_ignoreartist: @@ -135,7 +135,7 @@ class CleanerAgent: t = re.sub(r" \(originally by .*?\)","",t) t = re.sub(r" \(.*?Remaster.*?\)","",t) - for s in settings.get_settings("REMOVE_FROM_TITLE"): + for s in malojaconfig["DELIMITERS_FEAT"]: if s in t: t = t.replace(s,"") diff --git a/maloja/database.py b/maloja/database.py index a1b83fc..bbe1a7f 100644 --- a/maloja/database.py +++ b/maloja/database.py @@ -283,7 +283,7 @@ def info(): artists = {} return { - "name":settings.get_settings("NAME"), + "name":malojaconfig["NAME"], "artists":{ chartentry["artist"]:round(chartentry["scrobbles"] * 100 / totalscrobbles,3) for chartentry in get_charts_artists() if chartentry["scrobbles"]/totalscrobbles >= 0 @@ -476,7 +476,7 @@ def trackInfo(track): scrobbles = c["scrobbles"] position = c["rank"] cert = None - threshold_gold, threshold_platinum, threshold_diamond = settings.get_settings("SCROBBLES_GOLD","SCROBBLES_PLATINUM","SCROBBLES_DIAMOND") + threshold_gold, threshold_platinum, threshold_diamond = malojaconfig["SCROBBLES_GOLD","SCROBBLES_PLATINUM","SCROBBLES_DIAMOND"] if scrobbles >= threshold_diamond: cert = "diamond" elif scrobbles >= threshold_platinum: cert = "platinum" elif scrobbles >= threshold_gold: cert = "gold" @@ -742,7 +742,7 @@ def build_db(): scrobblenum = len(db) log(f"Found {scrobblenum} scrobbles...") - usebar = not settings.get_settings("CLEAN_OUTPUT") + usebar = not malojaconfig["CLEAN_OUTPUT"] if usebar: pbar = ProgressBar(max=scrobblenum,prefix="Loading scrobbles") else: n = 0 @@ -860,7 +860,7 @@ def sync(): import copy -if settings.get_settings("USE_DB_CACHE"): +if malojaconfig["USE_DB_CACHE"]: def db_query(**kwargs): return db_query_cached(**kwargs) def db_aggregate(**kwargs): @@ -872,8 +872,8 @@ else: return db_aggregate_full(**kwargs) -csz = settings.get_settings("DB_CACHE_ENTRIES") -cmp = settings.get_settings("DB_MAX_MEMORY") +csz = malojaconfig["DB_CACHE_ENTRIES"] +cmp = malojaconfig["DB_MAX_MEMORY"] try: import psutil use_psutil = True @@ -885,8 +885,8 @@ cache_query_perm = lru.LRU(csz) cache_aggregate = lru.LRU(csz) cache_aggregate_perm = lru.LRU(csz) -perm_caching = settings.get_settings("CACHE_DATABASE_PERM") -temp_caching = settings.get_settings("CACHE_DATABASE_SHORT") +perm_caching = malojaconfig["CACHE_DATABASE_PERM"] +temp_caching = malojaconfig["CACHE_DATABASE_SHORT"] cachestats = { "cache_query":{ diff --git a/maloja/malojatime.py b/maloja/malojatime.py index 3355399..76c13a3 100644 --- a/maloja/malojatime.py +++ b/maloja/malojatime.py @@ -2,10 +2,11 @@ from datetime import timezone, timedelta, date, time, datetime from calendar import monthrange from os.path import commonprefix import math -from doreah.settings import get_settings + +from .globalconf import malojaconfig -OFFSET = get_settings("TIMEZONE") +OFFSET = malojaconfig["TIMEZONE"] TIMEZONE = timezone(timedelta(hours=OFFSET)) UTC = timezone.utc @@ -486,7 +487,7 @@ def timestamp_desc(t,short=False): timeobj = datetime.fromtimestamp(t,tz=TIMEZONE) - if not short: return timeobj.strftime(get_settings("TIME_FORMAT")) + if not short: return timeobj.strftime(malojaconfig["TIMEZONE"]) difference = int(datetime.now().timestamp() - t) diff --git a/maloja/proccontrol/control.py b/maloja/proccontrol/control.py index 0feed3c..8eb8d91 100644 --- a/maloja/proccontrol/control.py +++ b/maloja/proccontrol/control.py @@ -45,7 +45,7 @@ def start(): sp = subprocess.Popen(["python3","-m","maloja.proccontrol.supervisor"],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL) print(col["green"]("Maloja started!")) - port = settings.get_settings("WEB_PORT") + port = malojaconfig["WEB_PORT"] print("Visit your server address (Port " + str(port) + ") to see your web interface. Visit /admin_setup to get started.") print("If you're installing this on your local machine, these links should get you there:") diff --git a/maloja/proccontrol/setup.py b/maloja/proccontrol/setup.py index 587e2f1..0f61e00 100644 --- a/maloja/proccontrol/setup.py +++ b/maloja/proccontrol/setup.py @@ -1,11 +1,10 @@ import pkg_resources from distutils import dir_util -from doreah import settings from doreah.io import col, ask, prompt from doreah import auth import os -from ..globalconf import data_dir, dir_settings +from ..globalconf import data_dir, dir_settings, malojaconfig # EXTERNAL API KEYS @@ -32,17 +31,17 @@ def randomstring(length=32): def setup(): copy_initial_local_files() - SKIP = settings.get_settings("SKIP_SETUP") + SKIP = malojaconfig["SKIP_SETUP"] 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) + key = malojaconfig[k] if key is False: print("\t" + "Currently not using a " + apikeys[k] + " for image display.") elif key is None or key == "ASK": print("\t" + "Please enter your " + col['gold'](apikeys[k]) + ". If you do not want to use one at this moment, simply leave this empty and press Enter.") key = prompt("",types=(str,),default=False,skip=SKIP) - settings.update_settings(data_dir['settings']("settings.ini"),{k:key},create_new=True) + malojaconfig[k] = key else: print("\t" + apikeys[k] + " found.") @@ -57,8 +56,8 @@ def setup(): keyfile.write(key + "\t" + "Default Generated Key") # PASSWORD - defaultpassword = settings.get_settings("DEFAULT_PASSWORD") - forcepassword = settings.get_settings("FORCE_PASSWORD") + defaultpassword = malojaconfig["DEFAULT_PASSWORD"] + forcepassword = malojaconfig["FORCE_PASSWORD"] # this is mainly meant for docker, supply password via environment variable if forcepassword is not None: @@ -79,13 +78,14 @@ def setup(): # 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) - if settings.get_settings("NAME") is None: + if malojaconfig["NAME"] is None: 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="Generic Maloja User",skip=SKIP) - settings.update_settings(data_dir['settings']("settings.ini"),{"NAME":name},create_new=True) + malojaconfig["NAME"] = name - if settings.get_settings("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) if answer: - settings.update_settings(data_dir['settings']("settings.ini"),{"SEND_STATS":True,"PUBLIC_URL":None},create_new=True) + malojaconfig["SEND_STATS"] = True + malojaconfig["PUBLIC_URL"] = None else: - settings.update_settings(data_dir['settings']("settings.ini"),{"SEND_STATS":False},create_new=True) + malojaconfig["SEND_STATS"] = False diff --git a/maloja/proccontrol/supervisor.py b/maloja/proccontrol/supervisor.py index 097ca3a..102ac7c 100644 --- a/maloja/proccontrol/supervisor.py +++ b/maloja/proccontrol/supervisor.py @@ -5,8 +5,8 @@ import subprocess import setproctitle import signal from doreah.logging import log -from doreah.settings import get_settings +from .globalconf import malojaconfig from .control import getInstance @@ -33,7 +33,7 @@ def start(): while True: log("Maloja is not running, starting...",module="supervisor") - if get_settings("UPDATE_AFTER_CRASH"): + if malojaconfig["UPDATE_AFTER_CRASH"]: update() process = start() diff --git a/maloja/server.py b/maloja/server.py index 85214d7..2203ba2 100644 --- a/maloja/server.py +++ b/maloja/server.py @@ -47,8 +47,8 @@ import urllib #settings.config(files=["settings/default.ini","settings/settings.ini"]) #settings.update("settings/default.ini","settings/settings.ini") -MAIN_PORT = settings.get_settings("WEB_PORT") -HOST = settings.get_settings("HOST") +MAIN_PORT = malojaconfig["WEB_PORT"] +HOST = malojaconfig["HOST"] THREADS = 24 BaseRequest.MEMFILE_MAX = 15 * 1024 * 1024 @@ -90,7 +90,7 @@ css = generate_css() def clean_html(inp): return inp - #if settings.get_settings("DEV_MODE"): return inp + #if malojaconfig["DEV_MODE"]: return inp #else: return html_minify(inp) @@ -218,7 +218,7 @@ def static_image(pth): def get_css(): response.content_type = 'text/css' global css - if settings.get_settings("DEV_MODE"): css = generate_css() + if malojaconfig["DEV_MODE"]: css = generate_css() return css @@ -263,7 +263,7 @@ def static_html(name): except (ValueError, IndexError) as e: abort(404,"This Artist or Track does not exist") - if settings.get_settings("DEV_MODE"): jinja_environment.cache.clear() + if malojaconfig["DEV_MODE"]: jinja_environment.cache.clear() log("Generated page {name} in {time:.5f}s".format(name=name,time=clock.stop()),module="debug_performance") return clean_html(res) diff --git a/maloja/thirdparty/__init__.py b/maloja/thirdparty/__init__.py index 9acc691..c3ec838 100644 --- a/maloja/thirdparty/__init__.py +++ b/maloja/thirdparty/__init__.py @@ -10,9 +10,9 @@ import xml.etree.ElementTree as ElementTree import json import urllib.parse, urllib.request import base64 -from doreah.settings import get_settings from doreah.logging import log +from ..globalconf import malojaconfig services = { @@ -69,7 +69,7 @@ class GenericInterface: # populate from settings file once on creation # avoid constant disk access, restart on adding services is acceptable for key in self.settings: - self.settings[key] = get_settings(self.settings[key]) + self.settings[key] = malojaconfig[self.settings[key]] self.authorize() # this makes sure that of every class we define, we immediately create an @@ -105,7 +105,7 @@ class ProxyScrobbleInterface(GenericInterface,abstract=True): def active_proxyscrobble(self): return ( all(self.settings[key] not in [None,"ASK",False] for key in self.proxyscrobble["required_settings"]) and - get_settings(self.proxyscrobble["activated_setting"]) + malojaconfig[self.proxyscrobble["activated_setting"]] ) def scrobble(self,artists,title,timestamp): @@ -130,7 +130,7 @@ class ImportInterface(GenericInterface,abstract=True): def active_import(self): return ( all(self.settings[key] not in [None,"ASK",False] for key in self.scrobbleimport["required_settings"]) and - get_settings(self.scrobbleimport["activated_setting"]) + malojaconfig[self.scrobbleimport["activated_setting"]] ) @@ -147,7 +147,7 @@ class MetadataInterface(GenericInterface,abstract=True): def active_metadata(self): return ( all(self.settings[key] not in [None,"ASK",False] for key in self.metadata["required_settings"]) and - self.identifier in get_settings("METADATA_PROVIDERS") + self.identifier in malojaconfig["METADATA_PROVIDERS"] ) def get_image_track(self,track): @@ -228,5 +228,5 @@ from . import * services["metadata"].sort( - key=lambda provider : get_settings("METADATA_PROVIDERS").index(provider.identifier) + key=lambda provider : malojaconfig["METADATA_PROVIDERS"].index(provider.identifier) ) diff --git a/maloja/utilities/images.py b/maloja/utilities/images.py index 0bc1792..69e4476 100644 --- a/maloja/utilities/images.py +++ b/maloja/utilities/images.py @@ -34,8 +34,8 @@ else: ### Caches -cacheage = settings.get_settings("CACHE_EXPIRE_POSITIVE") * 24 * 3600 -cacheage_neg = settings.get_settings("CACHE_EXPIRE_NEGATIVE") * 24 * 3600 +cacheage = malojaconfig["CACHE_EXPIRE_POSITIVE"] * 24 * 3600 +cacheage_neg = malojaconfig["CACHE_EXPIRE_NEGATIVE"] * 24 * 3600 artist_cache = caching.Cache(name="imgcache_artists",maxage=cacheage,maxage_negative=cacheage_neg,persistent=True) track_cache = caching.Cache(name="imgcache_tracks",maxage=cacheage,maxage_negative=cacheage_neg,persistent=True) @@ -133,7 +133,7 @@ def local_files(artist=None,artists=None,title=None): # these caches are there so we don't check all files every time, but return the same one -local_cache_age = settings.get_settings("LOCAL_IMAGE_ROTATE") +local_cache_age = malojaconfig["LOCAL_IMAGE_ROTATE"] local_artist_cache = caching.Cache(maxage=local_cache_age) local_track_cache = caching.Cache(maxage=local_cache_age) @@ -142,7 +142,7 @@ def getTrackImage(artists,title,fast=False): hashable_track = (frozenset(artists),title) # Prio 1: Local image - if settings.get_settings("USE_LOCAL_IMAGES"): + if malojaconfig["USE_LOCAL_IMAGES"]: try: return thumborize(local_track_cache.get(hashable_track)) except: @@ -189,7 +189,7 @@ def getTrackImage(artists,title,fast=False): def getArtistImage(artist,fast=False): # Prio 1: Local image - if settings.get_settings("USE_LOCAL_IMAGES"): + if malojaconfig["USE_LOCAL_IMAGES"]: try: return thumborize(local_artist_cache.get(artist)) except: diff --git a/maloja/utilities/maintenance.py b/maloja/utilities/maintenance.py index 9d26549..780ef5a 100644 --- a/maloja/utilities/maintenance.py +++ b/maloja/utilities/maintenance.py @@ -87,7 +87,7 @@ def update_weekly(): @daily def send_stats(): - if settings.get_settings("SEND_STATS"): + if malojaconfig["SEND_STATS"]: log("Sending daily stats report...") @@ -98,8 +98,8 @@ def send_stats(): "method":"POST", "headers":{"Content-Type": "application/json"}, "data":json.dumps({ - "name":settings.get_settings("NAME"), - "url":settings.get_settings("PUBLIC_URL"), + "name":malojaconfig["NAME"], + "url":malojaconfig["PUBLIC_URL"], "version":".".join(str(d) for d in version), "artists":len(ARTISTS), "tracks":len(TRACKS), From 6ccbf68923d9a5b4b236612b193c15ed048bc22b Mon Sep 17 00:00:00 2001 From: krateng Date: Sun, 19 Dec 2021 22:15:28 +0100 Subject: [PATCH 05/18] Replaced more settings calls, added missing settings --- maloja/apis/listenbrainz.py | 2 +- maloja/database.py | 3 +-- maloja/globalconf.py | 4 +++- maloja/server.py | 8 ++------ maloja/utilities/images.py | 4 ++-- maloja/utilities/maintenance.py | 2 +- 6 files changed, 10 insertions(+), 13 deletions(-) diff --git a/maloja/apis/listenbrainz.py b/maloja/apis/listenbrainz.py index 80f8ba1..a254ffa 100644 --- a/maloja/apis/listenbrainz.py +++ b/maloja/apis/listenbrainz.py @@ -3,7 +3,7 @@ from ._exceptions import * from .. import database import datetime -from .globalconf import malojaconfig +from ..globalconf import malojaconfig class Listenbrainz(APIHandler): diff --git a/maloja/database.py b/maloja/database.py index bbe1a7f..92e227a 100644 --- a/maloja/database.py +++ b/maloja/database.py @@ -10,12 +10,11 @@ from .malojauri import uri_to_internal, internal_to_uri, compose_querystring from .thirdparty import proxy_scrobble_all from .__pkginfo__ import version -from .globalconf import data_dir +from .globalconf import data_dir, malojaconfig # doreah toolkit from doreah.logging import log from doreah import tsv -from doreah import settings from doreah.caching import Cache, DeepCache from doreah.auth import authenticated_api, authenticated_api_with_alternate from doreah.io import ProgressBar diff --git a/maloja/globalconf.py b/maloja/globalconf.py index 9577397..236670d 100644 --- a/maloja/globalconf.py +++ b/maloja/globalconf.py @@ -246,7 +246,9 @@ malojaconfig = Configuration( "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), - "track_search_provider":(tp.String(), "Track Search Provider", 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":{ diff --git a/maloja/server.py b/maloja/server.py index 2203ba2..6473d92 100644 --- a/maloja/server.py +++ b/maloja/server.py @@ -21,7 +21,6 @@ from .globalconf import malojaconfig from .jinjaenv.context import jinja_environment from jinja2.exceptions import TemplateNotFound # doreah toolkit -from doreah import settings from doreah.logging import log from doreah.timing import Clock from doreah import auth @@ -44,10 +43,7 @@ import urllib ### TECHNICAL SETTINGS ##### - -#settings.config(files=["settings/default.ini","settings/settings.ini"]) -#settings.update("settings/default.ini","settings/settings.ini") -MAIN_PORT = malojaconfig["WEB_PORT"] +PORT = malojaconfig["PORT"] HOST = malojaconfig["HOST"] THREADS = 24 BaseRequest.MEMFILE_MAX = 15 * 1024 * 1024 @@ -330,7 +326,7 @@ def run_server(): try: #run(webserver, host=HOST, port=MAIN_PORT, server='waitress') - waitress.serve(webserver, host=HOST, port=MAIN_PORT, threads=THREADS) + waitress.serve(webserver, host=HOST, port=PORT, threads=THREADS) except OSError: log("Error. Is another Maloja process already running?") raise diff --git a/maloja/utilities/images.py b/maloja/utilities/images.py index 69e4476..cf44016 100644 --- a/maloja/utilities/images.py +++ b/maloja/utilities/images.py @@ -1,8 +1,8 @@ from .. import globalconf -from ..globalconf import data_dir +from ..globalconf import data_dir, malojaconfig from .. import thirdparty -from doreah import settings, caching +from doreah import caching from doreah.logging import log import itertools diff --git a/maloja/utilities/maintenance.py b/maloja/utilities/maintenance.py index 780ef5a..8181b62 100644 --- a/maloja/utilities/maintenance.py +++ b/maloja/utilities/maintenance.py @@ -1,8 +1,8 @@ from ..__pkginfo__ import version from ..malojatime import ranges, thisweek, thisyear +from ..globalconf import malojaconfig from doreah.regular import yearly, daily -from doreah import settings from doreah.logging import log import datetime From df22a595b84043e10883c463ab9050aed7e6a4f2 Mon Sep 17 00:00:00 2001 From: krateng Date: Sun, 19 Dec 2021 22:25:01 +0100 Subject: [PATCH 06/18] Replaced settings calls in jinja files --- maloja/jinjaenv/context.py | 4 ++-- maloja/web/jinja/abstracts/base.jinja | 2 +- maloja/web/jinja/charts_artists.jinja | 2 +- maloja/web/jinja/charts_tracks.jinja | 2 +- maloja/web/jinja/snippets/entityrow.jinja | 2 +- maloja/web/jinja/snippets/links.jinja | 2 +- maloja/web/jinja/snippets/timeselection.jinja | 4 ++-- maloja/web/jinja/start.jinja | 6 +++--- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/maloja/jinjaenv/context.py b/maloja/jinjaenv/context.py index 330d8da..d621251 100644 --- a/maloja/jinjaenv/context.py +++ b/maloja/jinjaenv/context.py @@ -1,8 +1,8 @@ from .. import database_packed from . import filters +from .globalconf import malojaconfig from .. import database, database_packed, malojatime, utilities, malojauri -from doreah import settings from doreah.regular import repeatdaily import urllib @@ -30,7 +30,7 @@ def update_jinja_environment(): "malojatime": malojatime, "utilities": utilities, "mlj_uri": malojauri, - "settings": settings.get_settings, + "settings": malojaconfig, # external "urllib": urllib, "math":math, diff --git a/maloja/web/jinja/abstracts/base.jinja b/maloja/web/jinja/abstracts/base.jinja index 2ea6362..c465aec 100644 --- a/maloja/web/jinja/abstracts/base.jinja +++ b/maloja/web/jinja/abstracts/base.jinja @@ -48,7 +48,7 @@ Get your own Maloja scrobble server on PyPI
- Maloja {% if settings("DEV_MODE") %}[Developer Mode]{% endif %} + Maloja {% if settings["DEV_MODE"] %}[Developer Mode]{% endif %}
diff --git a/maloja/web/jinja/charts_artists.jinja b/maloja/web/jinja/charts_artists.jinja index d7dc648..c5b6a13 100644 --- a/maloja/web/jinja/charts_artists.jinja +++ b/maloja/web/jinja/charts_artists.jinja @@ -35,7 +35,7 @@ -{% if settings('CHARTS_DISPLAY_TILES') %} +{% if settings['CHARTS_DISPLAY_TILES'] %} {% include 'partials/charts_artists_tiles.jinja' %}

{% endif %} diff --git a/maloja/web/jinja/charts_tracks.jinja b/maloja/web/jinja/charts_tracks.jinja index 31f7e09..e4779f7 100644 --- a/maloja/web/jinja/charts_tracks.jinja +++ b/maloja/web/jinja/charts_tracks.jinja @@ -37,7 +37,7 @@ -{% if settings('CHARTS_DISPLAY_TILES') %} +{% if settings['CHARTS_DISPLAY_TILES'] %} {% include 'partials/charts_tracks_tiles.jinja' %}

{% endif %} diff --git a/maloja/web/jinja/snippets/entityrow.jinja b/maloja/web/jinja/snippets/entityrow.jinja index 5d04899..fb2668f 100644 --- a/maloja/web/jinja/snippets/entityrow.jinja +++ b/maloja/web/jinja/snippets/entityrow.jinja @@ -10,7 +10,7 @@
{% if "artists" in entity %} - {% if settings('TRACK_SEARCH_PROVIDER') is not none %} + {% if settings['TRACK_SEARCH_PROVIDER'] %} {{ links.link_search(entity) }} {% endif %} diff --git a/maloja/web/jinja/snippets/links.jinja b/maloja/web/jinja/snippets/links.jinja index f765c1b..f66bd3b 100644 --- a/maloja/web/jinja/snippets/links.jinja +++ b/maloja/web/jinja/snippets/links.jinja @@ -62,7 +62,7 @@ {% macro link_search(entity) -%} {% set searchstr = (entity.artists + [entity.title]) | join(" ") | urlencode %} - {% set searchprovider = settings('TRACK_SEARCH_PROVIDER') | lower | replace(' ','') %} + {% set searchprovider = settings['TRACK_SEARCH_PROVIDER'] | lower | replace(' ','') %} {% set searchproviders = { "youtube":'https://www.youtube.com/results?search_query=', diff --git a/maloja/web/jinja/snippets/timeselection.jinja b/maloja/web/jinja/snippets/timeselection.jinja index 33ee6ba..99f1ef5 100644 --- a/maloja/web/jinja/snippets/timeselection.jinja +++ b/maloja/web/jinja/snippets/timeselection.jinja @@ -31,7 +31,7 @@ {% for r in xcurrent %} {% if r.range == limitkeys.timerange %} {{ r.localisation }} - {% elif r.heavy and settings('DISCOURAGE_CPU_HEAVY_STATS') %} + {% elif r.heavy and settings['DISCOURAGE_CPU_HEAVY_STATS'] %} {{ r.localisation }} {% else %} {{ r.localisation }} @@ -49,7 +49,7 @@ {# {% if all(r.keys[k] == allkeys[k] for k in r.keys) %} #} {% if r.replacekeys | map('compare_key_in_dicts',r.replacekeys,allkeys) | alltrue %} {{ r.localisation }} - {% elif r.heavy and settings('DISCOURAGE_CPU_HEAVY_STATS') %} + {% elif r.heavy and settings['DISCOURAGE_CPU_HEAVY_STATS'] %} {{ r.localisation }} {% else %} {{ r.localisation }} diff --git a/maloja/web/jinja/start.jinja b/maloja/web/jinja/start.jinja index edaee0b..0c0d112 100644 --- a/maloja/web/jinja/start.jinja +++ b/maloja/web/jinja/start.jinja @@ -4,9 +4,9 @@ {% block scripts %} From 1ec283f885af351161097a568ee7ec97d13e1000 Mon Sep 17 00:00:00 2001 From: krateng Date: Sun, 19 Dec 2021 23:40:30 +0100 Subject: [PATCH 07/18] Added descriptions, fixed various things --- .gitignore | 1 + maloja/globalconf.py | 38 ++++----- maloja/jinjaenv/context.py | 2 +- maloja/proccontrol/setup.py | 6 +- settings.md | 153 +++++++++++++++++++++++++----------- 5 files changed, 135 insertions(+), 65 deletions(-) diff --git a/.gitignore b/.gitignore index 5614825..4686ef7 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.note *.xcf nohup.out +*-old # currently not using /screenshot*.png diff --git a/maloja/globalconf.py b/maloja/globalconf.py index 236670d..409ddba 100644 --- a/maloja/globalconf.py +++ b/maloja/globalconf.py @@ -211,35 +211,35 @@ malojaconfig = Configuration( "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"), - "force_password":(tp.String(), "Force Password", None, "On startup, overwrite admin password with this one"), - "clean_output":(tp.Boolean(), "Avoid Mutable Console Output", False, "No console output that will cause problems when piped to other outputs") + "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", "::", "Use :: for default IPv6, 0.0.0.0 for default IPv4"), + "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(), "Days until images are refetched", 300), - "cache_expire_negative":(tp.Integer(), "Days until failed image fetches are reattempted", 30), + "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) + "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), - "scrobbles_platinum":(tp.Integer(), "Scrobbles for Platinum", 500), - "scrobbles_diamond":(tp.Integer(), "Scrobbles for Diamond", 1000), - "name":(tp.String(), "Name", "Maloja User") + "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']), + "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), @@ -252,18 +252,18 @@ malojaconfig = Configuration( }, "Database":{ - "invalid_artists":(tp.Set(tp.String()), "Invalid Artists", ["[Unknown Artist]","Unknown Artist","Spotify"]), - "remove_from_title":(tp.Set(tp.String()), "Remove from Title", ["(Original Mix)","(Radio Edit)","(Album Version)","(Explicit Version)","(Bonus Track)"]), - "delimiters_feat":(tp.Set(tp.String()), "Featuring Delimiters", ["ft.","ft","feat.","feat","featuring","Ft.","Ft","Feat.","Feat","Featuring"]), - "delimiters_informal":(tp.Set(tp.String()), "Informal Delimiters", ["vs.","vs","&"]), - "delimiters_formal":(tp.Set(tp.String()), "Formal Delimiters", [";","/"]) + "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), + "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), @@ -274,3 +274,5 @@ malojaconfig = Configuration( save_endpoint="/apis/mlj_1/settings" ) + +malojaconfig.render_help("settings.md") diff --git a/maloja/jinjaenv/context.py b/maloja/jinjaenv/context.py index d621251..323d669 100644 --- a/maloja/jinjaenv/context.py +++ b/maloja/jinjaenv/context.py @@ -1,6 +1,6 @@ from .. import database_packed from . import filters -from .globalconf import malojaconfig +from ..globalconf import malojaconfig from .. import database, database_packed, malojatime, utilities, malojauri from doreah.regular import repeatdaily diff --git a/maloja/proccontrol/setup.py b/maloja/proccontrol/setup.py index 0f61e00..1d0fb72 100644 --- a/maloja/proccontrol/setup.py +++ b/maloja/proccontrol/setup.py @@ -78,9 +78,11 @@ def setup(): # 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) - if malojaconfig["NAME"] is None: - 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="Generic Maloja User",skip=SKIP) + 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: 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) diff --git a/settings.md b/settings.md index ed20a27..7c59bcc 100644 --- a/settings.md +++ b/settings.md @@ -2,54 +2,119 @@ Technically, each setting can be set via environment variable or the settings fi Settings File | Environment Variable | Type | Description ------ | --------- | --------- | --------- + **Setup** -  | `MALOJA_DATA_DIRECTORY` | String | Use this directory to store all application files. Useful for docker. Overwrites all individually specified directories below. -  | `MALOJA_DIRECTORY_CONFIG` | String | Use this directory to store configuration files. -`DIRECTORY_STATE` | `MALOJA_DIRECTORY_STATE` | String | Use this directory to store state files. -`DIRECTORY_LOGS` | `MALOJA_DIRECTORY_LOGS` | String | Use this directory to store log files. -`DIRECTORY_CACHE` | `MALOJA_DIRECTORY_CACHE` | String | Use this directory to store cache files. -`SKIP_SETUP` | `MALOJA_SKIP_SETUP` | Boolean | Whether to make server startup non-interactive. Vital for docker. -  | `MALOJA_FORCE_PASSWORD` | String | Sets password for admin login in web interface. This should normally be done via the interactive prompt. -`CLEAN_OUTPUT` | `MALOJA_CLEAN_OUTPUT` | Boolean | Avoid mutable console output. Use if console output will be redirected e.g. to a web interface. + +`data_directory` | `MALOJA_DATA_DIRECTORY` | String | Folder for all user data. Overwrites all choices for specific directories. + +`directory_config` | `MALOJA_DIRECTORY_CONFIG` | String | Folder for config data. Only applied when global data directory is not set. + +`directory_state` | `MALOJA_DIRECTORY_STATE` | String | Folder for state data. Only applied when global data directory is not set. + +`directory_logs` | `MALOJA_DIRECTORY_LOGS` | String | Folder for log data. Only applied when global data directory is not set. + +`directory_cache` | `MALOJA_DIRECTORY_CACHE` | String | Folder for cache data. Only applied when global data directory is not set. + +`skip_setup` | `MALOJA_SKIP_SETUP` | Boolean | Make server setup process non-interactive. Vital for Docker. + +`force_password` | `MALOJA_FORCE_PASSWORD` | String | On startup, overwrite admin password with this one. This should usually only be done via environment variable in Docker. + +`clean_output` | `MALOJA_CLEAN_OUTPUT` | Boolean | Use if console output will be redirected e.g. to a web interface. + + **Debug** -`LOGGING` | `MALOJA_LOGGING` | Boolean | Enable logging -`DEV_MODE` | `MALOJA_DEV_MODE` | Boolean | Enable developer mode + +`logging` | `MALOJA_LOGGING` | Boolean | Enable Logging + +`dev_mode` | `MALOJA_DEV_MODE` | Boolean | Enable developer mode + + +**Network** + +`host` | `MALOJA_HOST` | String | Host for your server - most likely :: for IPv6 or 0.0.0.0 for IPv4 + +`port` | `MALOJA_PORT` | Integer | Port + + **Technical** -`WEB_PORT` |   | Integer | HTTP port to use for your web interface and API -`HOST` |   | String | Host for your server - most likely `::` for IPv6 or `0.0.0.0` for IPv4 -`CACHE_EXPIRE_POSITIVE` |   | Integer | Days until images are refetched -`CACHE_EXPIRE_NEGATIVE` |   | Integer | Days until failed image fetches are reattempted -`USE_DB_CACHE` |   | Boolean | Whether to use the Database Cache. -`CACHE_DATABASE_SHORT` |   | Boolean | Whether to use the Volatile DB Cache. -`CACHE_DATABASE_PERM` |   | Boolean | Whether to use the Permanent DB Cache. -`DB_CACHE_ENTRIES` |   | Integer | Maximal entries of cache. -`DB_MAX_MEMORY` |   | Integer | Maximal percentage of total 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) + +`cache_expire_positive` | `MALOJA_CACHE_EXPIRE_POSITIVE` | Integer | Days until images are refetched + +`cache_expire_negative` | `MALOJA_CACHE_EXPIRE_NEGATIVE` | Integer | Days until failed image fetches are reattempted + +`use_db_cache` | `MALOJA_USE_DB_CACHE` | Boolean | Use DB Cache + +`cache_database_short` | `MALOJA_CACHE_DATABASE_SHORT` | Boolean | Use volatile Database Cache + +`cache_database_perm` | `MALOJA_CACHE_DATABASE_PERM` | Boolean | Use permanent Database Cache + +`db_cache_entries` | `MALOJA_DB_CACHE_ENTRIES` | Integer | Maximal Cache entries + +`db_max_memory` | `MALOJA_DB_MAX_MEMORY` | Integer | 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` |   | Integer | How many scrobbles should be considered 'Gold' status for a track -`SCROBBLES_PLATINUM` |   | Integer | How many scrobbles should be considered 'Platinum' status for a track -`SCROBBLES_DIAMOND` |   | Integer | How many scrobbles should be considered 'Diamond' status for a track -`NAME` |   | String | Your Name for display + +`scrobbles_gold` | `MALOJA_SCROBBLES_GOLD` | Integer | How many scrobbles a track needs to be considered 'Gold' status + +`scrobbles_platinum` | `MALOJA_SCROBBLES_PLATINUM` | Integer | How many scrobbles a track needs to be considered 'Platinum' status + +`scrobbles_diamond` | `MALOJA_SCROBBLES_DIAMOND` | Integer | How many scrobbles a track needs to be considered 'Diamond' status + +`name` | `MALOJA_NAME` | String | Name + + **Third Party Services** -`METADATA_PROVIDERS` |   | List (String) | Which metadata providers should be used in what order. Musicbrainz is rate-limited and should not be used first. -`SCROBBLE_LASTFM` |   | Boolean | Proxy-scrobble to Last.fm -`LASTFM_API_KEY` |   | String | API key for Last.fm. Necessary if proxy-scrobbling to Last.fm or using it as a metadata provider -`LASTFM_API_SECRET` |   | String | API secret for Last.fm. Necessary if proxy-scrobbling to Last.fm or using it as a metadata provider -`SPOTIFY_API_ID` |   | String | API ID for Spotify. Necessary if using it as a metadata provider. -`SPOTIFY_API_SECRET` |   | String | API Secret for Spotify. Necessary if using it as a metadata provider. -`TRACK_SEARCH_PROVIDER` |   | String | Provider for track search next to scrobbles. None to disable. -`THUMBOR_SERVER` |   | String | URL of Thumbor server to serve custom artwork. -`THUMBOR_SECRET` |   | String | Secret of Thumbor server + +`metadata_providers` | `MALOJA_METADATA_PROVIDERS` | List | Which metadata providers should be used in what order. Musicbrainz is rate-limited and should not be used first. + +`scrobble_lastfm` | `MALOJA_SCROBBLE_LASTFM` | Boolean | Proxy-Scrobble to Last.fm + +`lastfm_api_key` | `MALOJA_LASTFM_API_KEY` | String | Last.fm API Key + +`lastfm_api_secret` | `MALOJA_LASTFM_API_SECRET` | String | Last.fm API Secret + +`spotify_api_id` | `MALOJA_SPOTIFY_API_ID` | String | Spotify API ID + +`spotify_api_secret` | `MALOJA_SPOTIFY_API_SECRET` | String | Spotify API Secret + +`audiodb_api_key` | `MALOJA_AUDIODB_API_KEY` | String | TheAudioDB API Key + +`track_search_provider` | `MALOJA_TRACK_SEARCH_PROVIDER` | String | Track Search Provider + +`send_stats` | `MALOJA_SEND_STATS` | Boolean | Send Statistics + + **Database** -`INVALID_ARTISTS` |   | List (String) | Artists that should be discarded immediately -`REMOVE_FROM_TITLE` |   | List (String) | Phrases that should be removed from song titles -`DELIMITERS_FEAT` |   | List (String) | Delimiters used for extra artists, even when in the title field -`DELIMITERS_INFORMAL` |   | List (String) | Delimiters in informal artist strings with spaces expected around them -`DELIMITERS_FORMAL` |   | List (String) | Delimiters used to tag multiple artists when only one tag field is available + +`invalid_artists` | `MALOJA_INVALID_ARTISTS` | Set | Artists that should be discarded immediately + +`remove_from_title` | `MALOJA_REMOVE_FROM_TITLE` | Set | Phrases that should be removed from song titles + +`delimiters_feat` | `MALOJA_DELIMITERS_FEAT` | Set | Delimiters used for extra artists, even when in the title field + +`delimiters_informal` | `MALOJA_DELIMITERS_INFORMAL` | Set | Delimiters in informal artist strings with spaces expected around them + +`delimiters_formal` | `MALOJA_DELIMITERS_FORMAL` | Set | Delimiters used to tag multiple artists when only one tag field is available + + **Web Interface** -`DEFAULT_RANGE_CHARTS_ARTISTS` |   | String | What range is shown per default for the tile view on the start page -`DEFAULT_RANGE_CHARTS_TRACKS` |   | String | What range is shown per default for the tile view on the start page -`DEFAULT_STEP_PULSE` |   | String | What steps are shown per default for the pulse view on the start page -`CHARTS_DISPLAY_TILES` |   | Boolean | Whether to show tiles on chart pages -`DISCOURAGE_CPU_HEAVY_STATS` |   | Boolean | Prevent visitors from mindlessly clicking on CPU-heavy options. Does not actually disable them for malicious actors! -`USE_LOCAL_IMAGES` |   | Boolean | Use local images if present -`LOCAL_IMAGE_ROTATE` |   | Integer | How many seconds to wait between rotating local images + +`default_range_charts_artists` | `MALOJA_DEFAULT_RANGE_CHARTS_ARTISTS` | Choice | Default Range Artist Charts + +`default_range_charts_tracks` | `MALOJA_DEFAULT_RANGE_CHARTS_TRACKS` | Choice | Default Range Track Charts + +`default_step_pulse` | `MALOJA_DEFAULT_STEP_PULSE` | Choice | Default Pulse Step + +`charts_display_tiles` | `MALOJA_CHARTS_DISPLAY_TILES` | Boolean | Display Chart Tiles + +`discourage_cpu_heavy_stats` | `MALOJA_DISCOURAGE_CPU_HEAVY_STATS` | Boolean | Prevent visitors from mindlessly clicking on CPU-heavy options. Does not actually disable them for malicious actors! + +`use_local_images` | `MALOJA_USE_LOCAL_IMAGES` | Boolean | Use Local Images + +`local_image_rotate` | `MALOJA_LOCAL_IMAGE_ROTATE` | Integer | Local Image Rotate + +`timezone` | `MALOJA_TIMEZONE` | Integer | UTC Offset + +`time_format` | `MALOJA_TIME_FORMAT` | String | Time Format + From ba96c8e14fb5ca29b1958e1f8205483af515ec2a Mon Sep 17 00:00:00 2001 From: krateng Date: Mon, 20 Dec 2021 00:15:22 +0100 Subject: [PATCH 08/18] More fixes --- maloja/globalconf.py | 5 ++-- maloja/malojatime.py | 2 +- settings.md | 62 -------------------------------------------- 3 files changed, 3 insertions(+), 66 deletions(-) diff --git a/maloja/globalconf.py b/maloja/globalconf.py index 409ddba..32473e1 100644 --- a/maloja/globalconf.py +++ b/maloja/globalconf.py @@ -271,8 +271,7 @@ malojaconfig = Configuration( } }, configfile=data_dir['settings']("settings.ini"), - save_endpoint="/apis/mlj_1/settings" + save_endpoint="/apis/mlj_1/settings", + env_prefix="MALOJA_" ) - -malojaconfig.render_help("settings.md") diff --git a/maloja/malojatime.py b/maloja/malojatime.py index 76c13a3..662ec85 100644 --- a/maloja/malojatime.py +++ b/maloja/malojatime.py @@ -487,7 +487,7 @@ def timestamp_desc(t,short=False): timeobj = datetime.fromtimestamp(t,tz=TIMEZONE) - if not short: return timeobj.strftime(malojaconfig["TIMEZONE"]) + if not short: return timeobj.strftime(malojaconfig["TIME_FORMAT"]) difference = int(datetime.now().timestamp() - t) diff --git a/settings.md b/settings.md index 7c59bcc..991377d 100644 --- a/settings.md +++ b/settings.md @@ -2,119 +2,57 @@ Technically, each setting can be set via environment variable or the settings fi Settings File | Environment Variable | Type | Description ------ | --------- | --------- | --------- - **Setup** - `data_directory` | `MALOJA_DATA_DIRECTORY` | String | Folder for all user data. Overwrites all choices for specific directories. - `directory_config` | `MALOJA_DIRECTORY_CONFIG` | String | Folder for config data. Only applied when global data directory is not set. - `directory_state` | `MALOJA_DIRECTORY_STATE` | String | Folder for state data. Only applied when global data directory is not set. - `directory_logs` | `MALOJA_DIRECTORY_LOGS` | String | Folder for log data. Only applied when global data directory is not set. - `directory_cache` | `MALOJA_DIRECTORY_CACHE` | String | Folder for cache data. Only applied when global data directory is not set. - `skip_setup` | `MALOJA_SKIP_SETUP` | Boolean | Make server setup process non-interactive. Vital for Docker. - `force_password` | `MALOJA_FORCE_PASSWORD` | String | On startup, overwrite admin password with this one. This should usually only be done via environment variable in Docker. - `clean_output` | `MALOJA_CLEAN_OUTPUT` | Boolean | Use if console output will be redirected e.g. to a web interface. - - **Debug** - `logging` | `MALOJA_LOGGING` | Boolean | Enable Logging - `dev_mode` | `MALOJA_DEV_MODE` | Boolean | Enable developer mode - - **Network** - `host` | `MALOJA_HOST` | String | Host for your server - most likely :: for IPv6 or 0.0.0.0 for IPv4 - `port` | `MALOJA_PORT` | Integer | Port - - **Technical** - `cache_expire_positive` | `MALOJA_CACHE_EXPIRE_POSITIVE` | Integer | Days until images are refetched - `cache_expire_negative` | `MALOJA_CACHE_EXPIRE_NEGATIVE` | Integer | Days until failed image fetches are reattempted - `use_db_cache` | `MALOJA_USE_DB_CACHE` | Boolean | Use DB Cache - `cache_database_short` | `MALOJA_CACHE_DATABASE_SHORT` | Boolean | Use volatile Database Cache - `cache_database_perm` | `MALOJA_CACHE_DATABASE_PERM` | Boolean | Use permanent Database Cache - `db_cache_entries` | `MALOJA_DB_CACHE_ENTRIES` | Integer | Maximal Cache entries - `db_max_memory` | `MALOJA_DB_MAX_MEMORY` | Integer | 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` | `MALOJA_SCROBBLES_GOLD` | Integer | How many scrobbles a track needs to be considered 'Gold' status - `scrobbles_platinum` | `MALOJA_SCROBBLES_PLATINUM` | Integer | How many scrobbles a track needs to be considered 'Platinum' status - `scrobbles_diamond` | `MALOJA_SCROBBLES_DIAMOND` | Integer | How many scrobbles a track needs to be considered 'Diamond' status - `name` | `MALOJA_NAME` | String | Name - - **Third Party Services** - `metadata_providers` | `MALOJA_METADATA_PROVIDERS` | List | Which metadata providers should be used in what order. Musicbrainz is rate-limited and should not be used first. - `scrobble_lastfm` | `MALOJA_SCROBBLE_LASTFM` | Boolean | Proxy-Scrobble to Last.fm - `lastfm_api_key` | `MALOJA_LASTFM_API_KEY` | String | Last.fm API Key - `lastfm_api_secret` | `MALOJA_LASTFM_API_SECRET` | String | Last.fm API Secret - `spotify_api_id` | `MALOJA_SPOTIFY_API_ID` | String | Spotify API ID - `spotify_api_secret` | `MALOJA_SPOTIFY_API_SECRET` | String | Spotify API Secret - `audiodb_api_key` | `MALOJA_AUDIODB_API_KEY` | String | TheAudioDB API Key - `track_search_provider` | `MALOJA_TRACK_SEARCH_PROVIDER` | String | Track Search Provider - `send_stats` | `MALOJA_SEND_STATS` | Boolean | Send Statistics - - **Database** - `invalid_artists` | `MALOJA_INVALID_ARTISTS` | Set | Artists that should be discarded immediately - `remove_from_title` | `MALOJA_REMOVE_FROM_TITLE` | Set | Phrases that should be removed from song titles - `delimiters_feat` | `MALOJA_DELIMITERS_FEAT` | Set | Delimiters used for extra artists, even when in the title field - `delimiters_informal` | `MALOJA_DELIMITERS_INFORMAL` | Set | Delimiters in informal artist strings with spaces expected around them - `delimiters_formal` | `MALOJA_DELIMITERS_FORMAL` | Set | Delimiters used to tag multiple artists when only one tag field is available - - **Web Interface** - `default_range_charts_artists` | `MALOJA_DEFAULT_RANGE_CHARTS_ARTISTS` | Choice | Default Range Artist Charts - `default_range_charts_tracks` | `MALOJA_DEFAULT_RANGE_CHARTS_TRACKS` | Choice | Default Range Track Charts - `default_step_pulse` | `MALOJA_DEFAULT_STEP_PULSE` | Choice | Default Pulse Step - `charts_display_tiles` | `MALOJA_CHARTS_DISPLAY_TILES` | Boolean | Display Chart Tiles - `discourage_cpu_heavy_stats` | `MALOJA_DISCOURAGE_CPU_HEAVY_STATS` | Boolean | Prevent visitors from mindlessly clicking on CPU-heavy options. Does not actually disable them for malicious actors! - `use_local_images` | `MALOJA_USE_LOCAL_IMAGES` | Boolean | Use Local Images - `local_image_rotate` | `MALOJA_LOCAL_IMAGE_ROTATE` | Integer | Local Image Rotate - `timezone` | `MALOJA_TIMEZONE` | Integer | UTC Offset - `time_format` | `MALOJA_TIME_FORMAT` | String | Time Format - From 5a2ec61d66c9e2dbbdc4013764ac30b59f3fd0b1 Mon Sep 17 00:00:00 2001 From: krateng Date: Mon, 20 Dec 2021 00:55:31 +0100 Subject: [PATCH 09/18] Updated requirements --- .gitignore | 5 +++-- maloja/__pkginfo__.py | 2 +- requirements.txt | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 4686ef7..4b68952 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,13 @@ # generic temporary / dev files *.pyc -*.sh -!/install_*.sh *.note *.xcf nohup.out *-old +# local actions +scripts/* + # currently not using /screenshot*.png diff --git a/maloja/__pkginfo__.py b/maloja/__pkginfo__.py index 1af1b55..e60218a 100644 --- a/maloja/__pkginfo__.py +++ b/maloja/__pkginfo__.py @@ -15,7 +15,7 @@ python_version = ">=3.6" requires = [ "bottle>=0.12.16", "waitress>=1.3", - "doreah>=1.6.12", + "doreah>=1.7.0", "nimrodel>=0.7.0", "setproctitle>=1.1.10", "wand>=0.5.4", diff --git a/requirements.txt b/requirements.txt index 225ee68..490a2ab 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,9 @@ bottle>=0.12.16 waitress>=1.3 -doreah>=1.6.12 +doreah>=1.7.0 nimrodel>=0.7.0 setproctitle>=1.1.10 wand>=0.5.4 -jinja2>2.11 +jinja2>=2.11 lru-dict>=1.1.6 css_html_js_minify>=2.5.5 From 77667e7066efb77f826c580a055c9cf06a42c0b9 Mon Sep 17 00:00:00 2001 From: krateng Date: Mon, 20 Dec 2021 02:29:22 +0100 Subject: [PATCH 10/18] Visual adjustments --- maloja/proccontrol/setup.py | 4 ++-- maloja/web/static/css/grisons.css | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/maloja/proccontrol/setup.py b/maloja/proccontrol/setup.py index 1d0fb72..93d1e43 100644 --- a/maloja/proccontrol/setup.py +++ b/maloja/proccontrol/setup.py @@ -37,13 +37,13 @@ def setup(): for k in apikeys: key = malojaconfig[k] if key is False: - print("\t" + "Currently not using a " + apikeys[k] + " for image display.") + print("\t" + "Currently not using a " + col['red'](apikeys[k]) + " for image display.") elif key is None or key == "ASK": print("\t" + "Please enter your " + col['gold'](apikeys[k]) + ". If you do not want to use one at this moment, simply leave this empty and press Enter.") key = prompt("",types=(str,),default=False,skip=SKIP) malojaconfig[k] = key else: - print("\t" + apikeys[k] + " found.") + print("\t" + col['green'](apikeys[k]) + " found.") # OWN API KEY diff --git a/maloja/web/static/css/grisons.css b/maloja/web/static/css/grisons.css index ea11e4d..625b877 100644 --- a/maloja/web/static/css/grisons.css +++ b/maloja/web/static/css/grisons.css @@ -138,6 +138,20 @@ a.hidelink:hover { +/** INPUTS **/ + +input[type="text"], input[type="number"] { + background-color: transparent; + border: 0px; + border-bottom: 1px solid var(--text-color); + color: white; +} + +input:focus { + outline: 0; + background-color: var(--base-color-accent-light); +} + From b212e6b9219366d40a4f36a463bd0a073c4e3bc7 Mon Sep 17 00:00:00 2001 From: krateng Date: Tue, 21 Dec 2021 06:09:46 +0100 Subject: [PATCH 11/18] Adjusted globalconfig to new configuration module --- maloja/globalconf.py | 431 ++++++++++++++++++------------------ maloja/proccontrol/setup.py | 24 +- 2 files changed, 222 insertions(+), 233 deletions(-) diff --git a/maloja/globalconf.py b/maloja/globalconf.py index 32473e1..aab5f71 100644 --- a/maloja/globalconf.py +++ b/maloja/globalconf.py @@ -1,11 +1,39 @@ import os -from doreah.settings import get_settings from doreah.settings import config as settingsconfig from doreah.configuration import Configuration from doreah.configuration import types as tp + +# USEFUL FUNCS 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 # 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 # 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 = { - "config":[ +### STEP 1 - find out where the settings file is +# 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", - usrfol - ], - "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") + user_data_dir ] -} - -sentinels = { - "config":"settings", - "state":"scrobbles", - "logs":None, - "cache":None, -} - -# check environ variables -stng_data = get_settings("DATA_DIRECTORY",files=[],environ_prefix="MALOJA_") -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 + # check if it exists anywhere else + for pth in potentialpaths: + if os.path.exists(pthj(pth,"settings")): + maloja_dir_config = pth + break + # new installation, pick where to put it + else: + # test if we can write to that location + for pth in potentialpaths: + if is_dir_usable(pth): + maloja_dir_config = pth break - except: - pass + else: + 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 = { - "auth":pthj(dir_settings['state'],"auth"), - "backups":pthj(dir_settings['state'],"backups"), - "images":pthj(dir_settings['state'],"images"), - "scrobbles":pthj(dir_settings['state'],"scrobbles"), - "rules":pthj(dir_settings['config'],"rules"), - "clients":pthj(dir_settings['config'],"clients"), - "settings":pthj(dir_settings['config'],"settings"), - "css":pthj(dir_settings['config'],"custom_css"), - "logs":pthj(dir_settings['logs']), - "cache":pthj(dir_settings['cache']), + "auth":pthj(top_dirs['state'],"auth"), + "backups":pthj(top_dirs['state'],"backups"), + "images":pthj(top_dirs['state'],"images"), + "scrobbles":pthj(top_dirs['state'],"scrobbles"), + "rules":pthj(top_dirs['config'],"rules"), + "clients":pthj(top_dirs['config'],"clients"), + "settings":pthj(top_dirs['config']), + "css":pthj(top_dirs['config'],"custom_css"), + "logs":pthj(top_dirs['logs']), + "cache":pthj(top_dirs['cache']), } @@ -144,13 +257,6 @@ data_dir = { from doreah import config config( - settings={ - "files":[ - data_dir['settings']("default.ini"), - data_dir['settings']("settings.ini") - ], - "environ_prefix":"MALOJA_" - }, caching={ "folder": data_dir['cache']() }, @@ -159,119 +265,14 @@ config( "cookieprefix":"maloja", "stylesheets":["/style.css"], "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={ - "logfolder": data_dir['logs']() if get_settings("LOGGING") else None + "logfolder": data_dir['logs']() if malojaconfig["LOGGING"] else None }, regular={ "autostart": False, - "offset": get_settings("TIMEZONE") + "offset": malojaconfig["TIMEZONE"] } ) 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_" - - ) diff --git a/maloja/proccontrol/setup.py b/maloja/proccontrol/setup.py index 93d1e43..867f86e 100644 --- a/maloja/proccontrol/setup.py +++ b/maloja/proccontrol/setup.py @@ -43,7 +43,7 @@ def setup(): key = prompt("",types=(str,),default=False,skip=SKIP) malojaconfig[k] = key else: - print("\t" + col['green'](apikeys[k]) + " found.") + print("\t" + col['lawngreen'](apikeys[k]) + " found.") # OWN API KEY @@ -56,7 +56,6 @@ def setup(): keyfile.write(key + "\t" + "Default Generated Key") # PASSWORD - defaultpassword = malojaconfig["DEFAULT_PASSWORD"] forcepassword = malojaconfig["FORCE_PASSWORD"] # this is mainly meant for docker, supply password via environment variable @@ -66,23 +65,12 @@ def setup(): print("Password has been set.") 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 defaultpassword is None: - # non-docker installation or user didn't set environment variable - defaultpassword = randomstring(32) - newpw = prompt("Please set a password for web backend access. Leave this empty to generate a random password.",skip=SKIP,secret=True) - 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) + newpw = prompt("Please set a password for web backend access. Leave this empty to generate a random password.",skip=SKIP,secret=True) + if newpw is None: + newpw = randomstring(32) + print("Generated password:",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: 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) From ef04c98ea7a6e12fcb3809dc9c4c4e4c6e77fbf3 Mon Sep 17 00:00:00 2001 From: krateng Date: Tue, 21 Dec 2021 06:09:58 +0100 Subject: [PATCH 12/18] Added new sentinel files for future --- maloja/data_files/cache/.maloja_cache_sentinel | 0 maloja/data_files/config/.maloja_config_sentinel | 0 maloja/data_files/logs/.maloja_logs_sentinel | 0 maloja/data_files/state/.maloja_state_sentinel | 0 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 maloja/data_files/cache/.maloja_cache_sentinel create mode 100644 maloja/data_files/config/.maloja_config_sentinel create mode 100644 maloja/data_files/logs/.maloja_logs_sentinel create mode 100644 maloja/data_files/state/.maloja_state_sentinel diff --git a/maloja/data_files/cache/.maloja_cache_sentinel b/maloja/data_files/cache/.maloja_cache_sentinel new file mode 100644 index 0000000..e69de29 diff --git a/maloja/data_files/config/.maloja_config_sentinel b/maloja/data_files/config/.maloja_config_sentinel new file mode 100644 index 0000000..e69de29 diff --git a/maloja/data_files/logs/.maloja_logs_sentinel b/maloja/data_files/logs/.maloja_logs_sentinel new file mode 100644 index 0000000..e69de29 diff --git a/maloja/data_files/state/.maloja_state_sentinel b/maloja/data_files/state/.maloja_state_sentinel new file mode 100644 index 0000000..e69de29 From e006a10f709fe81b2b47a9bd378120cd5fa626bd Mon Sep 17 00:00:00 2001 From: krateng Date: Tue, 21 Dec 2021 06:28:50 +0100 Subject: [PATCH 13/18] Removed old files --- maloja/data_files/cache/dummy | 0 maloja/data_files/config/settings/default.ini | 100 ------------------ 2 files changed, 100 deletions(-) delete mode 100644 maloja/data_files/cache/dummy delete mode 100644 maloja/data_files/config/settings/default.ini diff --git a/maloja/data_files/cache/dummy b/maloja/data_files/cache/dummy deleted file mode 100644 index e69de29..0000000 diff --git a/maloja/data_files/config/settings/default.ini b/maloja/data_files/config/settings/default.ini deleted file mode 100644 index 6bce77b..0000000 --- a/maloja/data_files/config/settings/default.ini +++ /dev/null @@ -1,100 +0,0 @@ -# Do not change settings in this file -# Instead, simply write an entry with the same name in your own settings.ini file -# Category headers in [brackets] are only for organization and not necessary - -[Directories] -# DATA_DIRECTORY determines the base directory. It should be specified as environment -# variable because this file itself is loaded from it. -# Configuration is always in this base directory. Other data defaults to be here -# too, but can be customized with the options below. -DIRECTORY_STATE = None # This is /var/lib/maloja per XDG -DIRECTORY_LOGS = None # this is /var/log/maloja per XDG -DIRECTORY_CACHE = None # this is /var/cache/maloja per XDG - -[HTTP] - -WEB_PORT = 42010 -HOST = "::" # You most likely want either :: for IPv6 or 0.0.0.0 for IPv4 here - -[Login] - -DEFAULT_PASSWORD = none -FORCE_PASSWORD = none -# these are only meant for Docker containers -# on first start, set the environment variable MALOJA_DEFAULT_PASSWORD -# if you forgot and already generated a random password, you can overwrite it with MALOJA_FORCE_PASSWORD - -[Third Party Services] - -# order in which to use the metadata providers -# keep in mind that musicbrainz is rate-limited and should probably not be used first -METADATA_PROVIDERS = [lastfm,spotify,deezer,musicbrainz] -# whether to proxy scrobble to other services -SCROBBLE_LASTFM = false - -CACHE_EXPIRE_NEGATIVE = 30 # after how many days negative results should be tried again -CACHE_EXPIRE_POSITIVE = 300 # after how many days positive results should be refreshed -THUMBOR_SERVER = None -THUMBOR_SECRET = "" - -# Can be 'YouTube', 'YouTube Music', 'Spotify', 'Tidal', 'SoundCloud', 'Deezer', 'Amazon Music', 'Apple', 'Beatport', 'Bandcamp', 'Qobuz' -# Set to None to disable -TRACK_SEARCH_PROVIDER = None - -[Database] - -USE_DB_CACHE = yes -CACHE_DATABASE_SHORT = true -CACHE_DATABASE_PERM = true #more permanent cache for old timeranges -DB_CACHE_ENTRIES = 10000 #experiment with this depending on your RAM -DB_MAX_MEMORY = 75 # percentage of RAM utilization (whole container, not just maloja) that should trigger a flush -INVALID_ARTISTS = ["[Unknown Artist]","Unknown Artist","Spotify"] -REMOVE_FROM_TITLE = ["(Original Mix)","(Radio Edit)","(Album Version)","(Explicit Version)","(Bonus Track)"] -DELIMITERS_FEAT = ["ft.","ft","feat.","feat","featuring","Ft.","Ft","Feat.","Feat","Featuring"] -DELIMITERS_INFORMAL = ["vs.","vs","&"] -DELIMITERS_FORMAL = [";","/"] -USE_PARSE_PLUGINS = no - -[Local Images] - -USE_LOCAL_IMAGES = true -LOCAL_IMAGE_ROTATE = 3600 # when multiple images are present locally, how many seconds we wait between rotation - -[Web Interface] - -# what range is shown per default for the tile view on the start page -# can be week, month, year, alltime -DEFAULT_RANGE_CHARTS_ARTISTS = year -DEFAULT_RANGE_CHARTS_TRACKS = year -# same for pulse view -# can be day, week, month, year -DEFAULT_STEP_PULSE = month - -# display top tiles on artist and track chart pages -CHARTS_DISPLAY_TILES = false - -# this does not actually block any requests, it's just an interface feature t -# prevent visitors from mindlessly clicking on those options and hogging your cpu -DISCOURAGE_CPU_HEAVY_STATS = false - -# Offset in hours to UTC -TIMEZONE = 0 -TIME_FORMAT = "%d. %b %Y %I:%M %p" # use '%H:%M' instead of '%I:%M %p' for 24 hour clock - -[Fluff] - -# how many scrobbles a track needs to aquire this status -SCROBBLES_GOLD = 250 -SCROBBLES_PLATINUM = 500 -SCROBBLES_DIAMOND = 1000 -# name for comparisons -NAME = None - -[Misc] - -SKIP_SETUP = no -LOGGING = true -DEV_MODE = false - -# set this to true if your console output will be processed and should never change existing lines -CLEAN_OUTPUT = false From e94607dc2cdfb0f08b95e990446689f7ee87a0cf Mon Sep 17 00:00:00 2001 From: krateng Date: Tue, 21 Dec 2021 06:55:35 +0100 Subject: [PATCH 14/18] Finished globalconf rework (I hope?) --- maloja/globalconf.py | 226 ++++++++++++++++++++++++------------------- 1 file changed, 124 insertions(+), 102 deletions(-) diff --git a/maloja/globalconf.py b/maloja/globalconf.py index aab5f71..7d93c62 100644 --- a/maloja/globalconf.py +++ b/maloja/globalconf.py @@ -4,6 +4,19 @@ from doreah.configuration import Configuration from doreah.configuration import types as tp + +# 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 +# otherwise, each directory is treated seperately +# in that case, individual settings for each are respected +# DIRECRORY_CONFIG, DIRECRORY_STATE, DIRECTORY_LOGS and DIRECTORY_CACHE +# config can only be determined by environment variable, the others can be loaded +# from the config files +# explicit settings will always be respected. if there are none: +# first check if there is any indication of one of the possibilities being populated already +# if not, use the first we have permissions for +# after we decide which to use, fix it in settings to avoid future heuristics + # USEFUL FUNCS pthj = os.path.join @@ -21,31 +34,67 @@ def get_env_vars(key,pathsuffix=[]): -# get user dirs from environment -user_dirs = {} +directory_info = { + "config":{ + "sentinel":"settings", + "possible_folders":[ + "/etc/maloja", + os.path.expanduser("~/.local/share/maloja") + ], + "setting":"directory_config" + }, + "cache":{ + "sentinel":"dummy", + "possible_folders":[ + "/var/cache/maloja", + os.path.expanduser("~/.local/share/maloja/cache") + ], + "setting":"directory_cache" + }, + "state":{ + "sentinel":"scrobbles", + "possible_folders":[ + "/var/lib/maloja", + os.path.expanduser("~/.local/share/maloja") + ], + "setting":"directory_state" + }, + "logs":{ + "sentinel":"dbfix", + "possible_folders":[ + "/var/log/maloja", + os.path.expanduser("~/.local/share/maloja/logs") + ], + "setting":"directory_logs" + } +} + +# function that +# 1) checks if folder has been specified by user +# 2) if not, checks if one has been in use before and writes it to dict/config +# 3) if not, determines which to use and writes it to dict/config +# returns determined folder +def find_good_folder(datatype,configobject): + info = directory_info[datatype] + + # 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) + configobject[info['setting']] = p + return p + + 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) + configobject[info['setting']] = p + return p + print("No folder can be used for",datatype) + print("This should not happen!") -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 -# but with asynnetrical structure, cache and logs in subfolders -# otherwise, each directory is treated seperately -# in that case, individual settings for each are respected -# DIRECRORY_CONFIG, DIRECRORY_STATE, DIRECTORY_LOGS and DIRECTORY_CACHE -# config can only be determined by environment variable, the others can be loaded -# from the config files -# explicit settings will always be respected. if there are none: -# first check if there is any indication of one of the possibilities being populated already -# if not, use the first we have permissions for -# after we decide which to use, fix it in settings to avoid future heuristics @@ -53,25 +102,13 @@ user_data_dir = pthj(user_data_dir,"maloja") # 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", - user_data_dir - ] - # check if it exists anywhere else - for pth in potentialpaths: - if os.path.exists(pthj(pth,"settings")): - maloja_dir_config = pth - break - # new installation, pick where to put it - else: - # test if we can write to that location - for pth in potentialpaths: - if is_dir_usable(pth): - maloja_dir_config = pth - break - else: - print("Could not find a proper path to put settings file. Please check your permissions!") + maloja_dir_config = find_good_folder('config',{}) + found_new_config_dir = True +else: + found_new_config_dir = False + # remember whether we had to find our config dir or it was user-specified oldsettingsfile = pthj(maloja_dir_config,"settings","settings.ini") newsettingsfile = pthj(maloja_dir_config,"settings.ini") @@ -156,72 +193,52 @@ malojaconfig = Configuration( ) -malojaconfig["DIRECTORY_CONFIG"] = maloja_dir_config +if found_new_config_dir: + malojaconfig["DIRECTORY_CONFIG"] = maloja_dir_config + # this really doesn't matter because when are we gonna load info about where + # the settings file is stored from the settings file + # but oh well + +malojaconfig.render_help(pthj(maloja_dir_config,"settings.md"), + top_text='''If you wish to adjust settings in the settings.ini file, do so while the server +is not running in order to avoid data being overwritten. + +Technically, each setting can be set via environment variable or the settings +file - simply add the prefix `MALOJA_` for environment variables. It is recommended +to use the settings file where possible and not configure each aspect of your +server via environment variables!''') ### 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!") +for datatype in ("state","cache","logs"): + # obviously default values shouldn't trigger this + # if user has nothing specified, we need to use this + if malojaconfig.get_specified(directory_info[datatype]['setting']) is None and malojaconfig.get_specified('DATA_DIRECTORY') is None: + find_good_folder(datatype,malojaconfig) + + + + + + +### STEP 4 - this is where all the guessing about previous installation ends +### we have our definite settings and are now just generating the real +### folder names for everything + if malojaconfig['DATA_DIRECTORY'] is None: - top_dirs = { + dir_settings = { "config":malojaconfig['DIRECTORY_CONFIG'], "state":malojaconfig['DIRECTORY_STATE'], "cache":malojaconfig['DIRECTORY_CACHE'], "logs":malojaconfig['DIRECTORY_LOGS'], } else: - top_dirs = { + dir_settings = { "config":malojaconfig['DATA_DIRECTORY'], "state":malojaconfig['DATA_DIRECTORY'], "cache":pthj(malojaconfig['DATA_DIRECTORY'],"cache"), @@ -231,16 +248,16 @@ else: data_directories = { - "auth":pthj(top_dirs['state'],"auth"), - "backups":pthj(top_dirs['state'],"backups"), - "images":pthj(top_dirs['state'],"images"), - "scrobbles":pthj(top_dirs['state'],"scrobbles"), - "rules":pthj(top_dirs['config'],"rules"), - "clients":pthj(top_dirs['config'],"clients"), - "settings":pthj(top_dirs['config']), - "css":pthj(top_dirs['config'],"custom_css"), - "logs":pthj(top_dirs['logs']), - "cache":pthj(top_dirs['cache']), + "auth":pthj(dir_settings['state'],"auth"), + "backups":pthj(dir_settings['state'],"backups"), + "images":pthj(dir_settings['state'],"images"), + "scrobbles":pthj(dir_settings['state'],"scrobbles"), + "rules":pthj(dir_settings['config'],"rules"), + "clients":pthj(dir_settings['config'],"clients"), + "settings":pthj(dir_settings['config']), + "css":pthj(dir_settings['config'],"custom_css"), + "logs":pthj(dir_settings['logs']), + "cache":pthj(dir_settings['cache']), } @@ -276,3 +293,8 @@ config( ) settingsconfig._readpreconfig() + +# what the fuck did i just write +# this spaghetti file is proudly sponsored by the rice crackers i'm eating at the +# moment as well as some cute chinese girl whose asmr i'm listening to in the +# background. and now to bed! From 97e8d5b18d5a05a40b9775d468af106895577003 Mon Sep 17 00:00:00 2001 From: krateng Date: Tue, 21 Dec 2021 07:11:24 +0100 Subject: [PATCH 15/18] Removed thumbor --- maloja/utilities/images.py | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/maloja/utilities/images.py b/maloja/utilities/images.py index cf44016..0227225 100644 --- a/maloja/utilities/images.py +++ b/maloja/utilities/images.py @@ -1,4 +1,3 @@ -from .. import globalconf from ..globalconf import data_dir, malojaconfig from .. import thirdparty @@ -15,20 +14,6 @@ import re import datetime -if globalconf.USE_THUMBOR: - def thumborize(url): - if url.startswith("/"): url = globalconf.OWNURL + url - encrypted_url = globalconf.THUMBOR_GENERATOR.generate( - width=300, - height=300, - smart=True, - image_url=url - ) - return globalconf.THUMBOR_SERVER + encrypted_url - -else: - def thumborize(url): - return url @@ -144,7 +129,7 @@ def getTrackImage(artists,title,fast=False): # Prio 1: Local image if malojaconfig["USE_LOCAL_IMAGES"]: try: - return thumborize(local_track_cache.get(hashable_track)) + return local_track_cache.get(hashable_track) except: images = local_files(artists=artists,title=title) if len(images) != 0: @@ -156,7 +141,7 @@ def getTrackImage(artists,title,fast=False): # Prio 2: Cached remote link try: result = track_cache.get(hashable_track) - if result is not None: return thumborize(result) + if result is not None: return result # if we have cached the nonexistence of that image, we immediately return # the redirect to the artist and let the resolver handle it # (even if we're not in a fast lookup right now) @@ -179,7 +164,7 @@ def getTrackImage(artists,title,fast=False): # cache results (even negative ones) track_cache.add(hashable_track,result) # return either result or redirect to artist - if result is not None: return thumborize(result) + if result is not None: return result for a in artists: res = getArtistImage(artist=a,fast=False) if res != "": return res @@ -191,19 +176,19 @@ def getArtistImage(artist,fast=False): # Prio 1: Local image if malojaconfig["USE_LOCAL_IMAGES"]: try: - return thumborize(local_artist_cache.get(artist)) + return local_artist_cache.get(artist) except: images = local_files(artist=artist) if len(images) != 0: res = random.choice(images) local_artist_cache.add(artist,res) - return thumborize(urllib.parse.quote(res)) + return urllib.parse.quote(res) # Prio 2: Cached remote link try: result = artist_cache.get(artist) - if result is not None: return thumborize(result) + if result is not None: return result else: return "" # none means non-existence is cached, return empty except: @@ -219,7 +204,7 @@ def getArtistImage(artist,fast=False): result = thirdparty.get_image_artist_all(artist) # cache results (even negative ones) artist_cache.add(artist,result) #cache_artist(artist,result) - if result is not None: return thumborize(result) + if result is not None: return result else: return "" def getTrackImages(trackobjectlist,fast=False): From 7299c2e07ee77b8ed3075f746bab1eeb988166b4 Mon Sep 17 00:00:00 2001 From: krateng Date: Tue, 21 Dec 2021 07:30:38 +0100 Subject: [PATCH 16/18] Finishing touches --- maloja/globalconf.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/maloja/globalconf.py b/maloja/globalconf.py index 7d93c62..9e672f2 100644 --- a/maloja/globalconf.py +++ b/maloja/globalconf.py @@ -36,7 +36,7 @@ def get_env_vars(key,pathsuffix=[]): directory_info = { "config":{ - "sentinel":"settings", + "sentinel":"rules", "possible_folders":[ "/etc/maloja", os.path.expanduser("~/.local/share/maloja") @@ -80,19 +80,19 @@ def find_good_folder(datatype,configobject): # 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) + #print(p,"has been determined as maloja's folder for",datatype) configobject[info['setting']] = p return p - print("Could not find previous",datatype,"folder") + #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) + #print(p,"has been selected as maloja's folder for",datatype) configobject[info['setting']] = p return p - print("No folder can be used for",datatype) - print("This should not happen!") + #print("No folder can be used for",datatype) + #print("This should not happen!") @@ -246,7 +246,6 @@ else: } - data_directories = { "auth":pthj(dir_settings['state'],"auth"), "backups":pthj(dir_settings['state'],"backups"), From ca78463989a33ade2796a4b3aa44ef14b59ad7a2 Mon Sep 17 00:00:00 2001 From: krateng Date: Tue, 21 Dec 2021 19:58:20 +0100 Subject: [PATCH 17/18] Updated requirements --- maloja/__pkginfo__.py | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/maloja/__pkginfo__.py b/maloja/__pkginfo__.py index e60218a..ac286b8 100644 --- a/maloja/__pkginfo__.py +++ b/maloja/__pkginfo__.py @@ -15,7 +15,7 @@ python_version = ">=3.6" requires = [ "bottle>=0.12.16", "waitress>=1.3", - "doreah>=1.7.0", + "doreah>=1.7.1", "nimrodel>=0.7.0", "setproctitle>=1.1.10", "wand>=0.5.4", diff --git a/requirements.txt b/requirements.txt index 490a2ab..e761615 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ bottle>=0.12.16 waitress>=1.3 -doreah>=1.7.0 +doreah>=1.7.1 nimrodel>=0.7.0 setproctitle>=1.1.10 wand>=0.5.4 From 3ee68e75ac6531f99901a420b9105d07725a5c2b Mon Sep 17 00:00:00 2001 From: krateng Date: Tue, 21 Dec 2021 23:05:36 +0100 Subject: [PATCH 18/18] Ready to finally merge, fix GH-25 --- README.md | 4 ++-- maloja/apis/native_v1.py | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3fedd34..b7cd4e6 100644 --- a/README.md +++ b/README.md @@ -108,11 +108,11 @@ to run the server in the foreground. ### Customization -* Have a look at the [available settings](settings.md) and specifiy your choices in `/etc/maloja/settings/settings.ini`. You can also set each of these settings as an environment variable with the prefix `MALOJA_` (e.g. `MALOJA_SKIP_SETUP`). +* Have a look at the [available settings](settings.md) and specifiy your choices in `/etc/maloja/settings.ini`. You can also set each of these settings as an environment variable with the prefix `MALOJA_` (e.g. `MALOJA_SKIP_SETUP`). * If you have activated admin mode in your web interface, you can upload custom images for artists or tracks by simply dragging them onto the existing image on the artist or track page. You can also manage custom images directly in the file system - consult `images.info` in the `/var/lib/maloja/images` folder. -* To specify custom rules, consult the `rules.info` file in `/etc/maloja/rules`. You can also apply some predefined rules on the `/setup` page of your server. +* To specify custom rules, consult the `rules.info` file in `/etc/maloja/rules`. You can also apply some predefined rules on the `/admin_setup` page of your server. ## How to scrobble diff --git a/maloja/apis/native_v1.py b/maloja/apis/native_v1.py index a9899a8..a046a0a 100644 --- a/maloja/apis/native_v1.py +++ b/maloja/apis/native_v1.py @@ -332,6 +332,4 @@ def newrule(**keys): @authenticated_api def set_settings(**keys): from .. import globalconf - from pprint import pprint - pprint(keys) globalconf.malojaconfig.update(keys)