From bb68afee122c0d0f04ac6a139a883df90f1adca2 Mon Sep 17 00:00:00 2001 From: krateng Date: Sat, 9 Apr 2022 20:55:50 +0200 Subject: [PATCH 01/39] Moved main process control to __main__ --- maloja/__main__.py | 145 +++++++++++++++++++++++++++++++++- maloja/proccontrol/control.py | 141 --------------------------------- maloja/server.py | 3 - pyproject.toml | 2 +- 4 files changed, 143 insertions(+), 148 deletions(-) delete mode 100644 maloja/proccontrol/control.py diff --git a/maloja/__main__.py b/maloja/__main__.py index 4fcd284..e26fdea 100644 --- a/maloja/__main__.py +++ b/maloja/__main__.py @@ -1,4 +1,143 @@ -# make the package itself runnable with python -m maloja +import os +import signal +import subprocess -from .proccontrol.control import main -main() +from setproctitle import setproctitle +from ipaddress import ip_address + +from doreah.control import mainfunction +from doreah.io import col + +from . import __pkginfo__ as pkginfo +from . import globalconf +from .proccontrol import tasks +from .proccontrol.setup import setup + + + +def print_header_info(): + print() + #print("#####") + print(col['yellow']("Maloja"),f"v{pkginfo.VERSION}") + print(pkginfo.HOMEPAGE) + #print("#####") + print() + + + +def get_instance(): + try: + return int(subprocess.check_output(["pidof","maloja"])) + except: + return None + +def get_instance_supervisor(): + try: + return int(subprocess.check_output(["pidof","maloja_supervisor"])) + except: + return None + +def restart(): + stop() + start() + + +def start(): + if get_instance_supervisor() is not None: + print("Maloja is already running.") + else: + print_header_info() + setup() + try: + #p = subprocess.Popen(["python3","-m","maloja.server"],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL) + sp = subprocess.Popen(["python3","-m","maloja.proccontrol.supervisor"],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL) + print(col["green"]("Maloja started!")) + + port = globalconf.malojaconfig["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:") + print("\t" + col["blue"]("http://localhost:" + str(port))) + print("\t" + col["blue"]("http://localhost:" + str(port) + "/admin_setup")) + return True + except: + print("Error while starting Maloja.") + return False + + +def stop(): + + pid_sv = get_instance_supervisor() + if pid_sv is not None: + os.kill(pid_sv,signal.SIGTERM) + + pid = get_instance() + if pid is not None: + os.kill(pid,signal.SIGTERM) + + if pid is None and pid_sv is None: + return False + + print("Maloja stopped!") + return True + +def onlysetup(): + print_header_info() + setup() + print("Setup complete!") + +def run_server(): + print_header_info() + setup() + setproctitle("maloja") + from . import server + server.run_server() + +def debug(): + os.environ["MALOJA_DEV_MODE"] = 'true' + globalconf.malojaconfig.load_environment() + direct() + +def print_info(): + print_header_info() + print(col['lightblue']("Configuration Directory:"),globalconf.dir_settings['config']) + print(col['lightblue']("Data Directory: "),globalconf.dir_settings['state']) + print(col['lightblue']("Log Directory: "),globalconf.dir_settings['logs']) + print(col['lightblue']("Network: "),f"IPv{ip_address(globalconf.malojaconfig['host']).version}, Port {globalconf.malojaconfig['port']}") + print(col['lightblue']("Timezone: "),f"UTC{globalconf.malojaconfig['timezone']:+d}") + print() + print() + +@mainfunction({"l":"level","v":"version","V":"version"},flags=['version','include_images'],shield=True) +def main(*args,**kwargs): + + actions = { + # server + "start":start, + "restart":restart, + "stop":stop, + "run":run_server, + "debug":debug, + "setup":onlysetup, + # admin scripts + "import":tasks.import_scrobbles, # maloja import /x/y.csv + "backup":tasks.backup, # maloja backup --targetfolder /x/y --include_images + "generate":tasks.generate, # maloja generate 400 + "export":tasks.export, # maloja export + # aux + "info":print_info + } + + if "version" in kwargs: + print(info.VERSION) + else: + try: + action, *args = args + action = actions[action] + except (ValueError, KeyError): + print("Valid commands: " + " ".join(a for a in actions)) + return + + return action(*args,**kwargs) + + return True diff --git a/maloja/proccontrol/control.py b/maloja/proccontrol/control.py deleted file mode 100644 index fd2aeba..0000000 --- a/maloja/proccontrol/control.py +++ /dev/null @@ -1,141 +0,0 @@ -import subprocess -from doreah import settings -from doreah.control import mainfunction -from doreah.io import col -import os -import signal -from ipaddress import ip_address - -from .setup import setup -from . import tasks -from .. import __pkginfo__ as info -from .. import globalconf - - - -def print_header_info(): - print() - #print("#####") - print(col['yellow']("Maloja"),"v" + info.VERSION) - print(info.HOMEPAGE) - #print("#####") - print() - - - -def getInstance(): - try: - output = subprocess.check_output(["pidof","Maloja"]) - return int(output) - except: - return None - -def getInstanceSupervisor(): - try: - output = subprocess.check_output(["pidof","maloja_supervisor"]) - return int(output) - except: - return None - -def restart(): - stop() - start() - -def start(): - if getInstanceSupervisor() is not None: - print("Maloja is already running.") - else: - print_header_info() - setup() - try: - #p = subprocess.Popen(["python3","-m","maloja.server"],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL) - sp = subprocess.Popen(["python3","-m","maloja.proccontrol.supervisor"],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL) - print(col["green"]("Maloja started!")) - - port = globalconf.malojaconfig["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:") - print("\t" + col["blue"]("http://localhost:" + str(port))) - print("\t" + col["blue"]("http://localhost:" + str(port) + "/admin_setup")) - return True - except: - print("Error while starting Maloja.") - return False - - -def stop(): - - pid_sv = getInstanceSupervisor() - if pid_sv is not None: - os.kill(pid_sv,signal.SIGTERM) - - pid = getInstance() - if pid is not None: - os.kill(pid,signal.SIGTERM) - - if pid is None and pid_sv is None: - return False - - print("Maloja stopped!") - return True - -def onlysetup(): - print_header_info() - setup() - print("Setup complete!") - -def direct(): - print_header_info() - setup() - from .. import server - server.run_server() - -def debug(): - os.environ["MALOJA_DEV_MODE"] = 'true' - globalconf.malojaconfig.load_environment() - direct() - -def print_info(): - print_header_info() - print(col['lightblue']("Configuration Directory:"),globalconf.dir_settings['config']) - print(col['lightblue']("Data Directory: "),globalconf.dir_settings['state']) - print(col['lightblue']("Log Directory: "),globalconf.dir_settings['logs']) - print(col['lightblue']("Network: "),f"IPv{ip_address(globalconf.malojaconfig['host']).version}, Port {globalconf.malojaconfig['port']}") - print(col['lightblue']("Timezone: "),f"UTC{globalconf.malojaconfig['timezone']:+d}") - print() - print() - -@mainfunction({"l":"level","v":"version","V":"version"},flags=['version','include_images'],shield=True) -def main(*args,**kwargs): - - actions = { - # server - "start":start, - "restart":restart, - "stop":stop, - "run":direct, - "debug":debug, - "setup":onlysetup, - # admin scripts - "import":tasks.import_scrobbles, # maloja import /x/y.csv - "backup":tasks.backup, # maloja backup --targetfolder /x/y --include_images - "generate":tasks.generate, # maloja generate 400 - "export":tasks.export, # maloja export - # aux - "info":print_info - } - - if "version" in kwargs: - print(info.VERSION) - else: - try: - action, *args = args - action = actions[action] - except (ValueError, KeyError): - print("Valid commands: " + " ".join(a for a in actions)) - return - - return action(*args,**kwargs) - - return True diff --git a/maloja/server.py b/maloja/server.py index 5975a39..7805152 100644 --- a/maloja/server.py +++ b/maloja/server.py @@ -2,7 +2,6 @@ import sys import os from threading import Thread -import setproctitle from importlib import resources from css_html_js_minify import html_minify, css_minify import datauri @@ -42,8 +41,6 @@ BaseRequest.MEMFILE_MAX = 15 * 1024 * 1024 webserver = Bottle() -#rename process, this is now required for the daemon manager to work -setproctitle.setproctitle("Maloja") ###### diff --git a/pyproject.toml b/pyproject.toml index c3d1c74..fa553b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,7 @@ full = [ ] [project.scripts] -maloja = "maloja.proccontrol.control:main" +maloja = "maloja:main" [build-system] requires = ["flit_core >=3.2,<4"] From 87f125062983a3f07102f7752eba489bf63ae202 Mon Sep 17 00:00:00 2001 From: krateng Date: Sat, 9 Apr 2022 21:02:17 +0200 Subject: [PATCH 02/39] Moved setup to top level --- maloja/__main__.py | 2 +- maloja/{proccontrol => }/setup.py | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) rename maloja/{proccontrol => }/setup.py (96%) diff --git a/maloja/__main__.py b/maloja/__main__.py index e26fdea..72a9d1a 100644 --- a/maloja/__main__.py +++ b/maloja/__main__.py @@ -11,7 +11,7 @@ from doreah.io import col from . import __pkginfo__ as pkginfo from . import globalconf from .proccontrol import tasks -from .proccontrol.setup import setup +from .setup import setup diff --git a/maloja/proccontrol/setup.py b/maloja/setup.py similarity index 96% rename from maloja/proccontrol/setup.py rename to maloja/setup.py index 8872357..beb6cd0 100644 --- a/maloja/proccontrol/setup.py +++ b/maloja/setup.py @@ -1,10 +1,12 @@ -from importlib import resources -from distutils import dir_util -from doreah.io import col, ask, prompt -from doreah import auth import os -from ..globalconf import data_dir, dir_settings, malojaconfig +from importlib import resources +from distutils import dir_util + +from doreah.io import col, ask, prompt +from doreah import auth + +from .globalconf import data_dir, dir_settings, malojaconfig @@ -48,7 +50,7 @@ def setup(): # OWN API KEY - from ..apis import apikeystore + from .apis import apikeystore if len(apikeystore) == 0: answer = ask("Do you want to set up a key to enable scrobbling? Your scrobble extension needs that key so that only you can scrobble tracks to your database.",default=True,skip=SKIP) if answer: From bceb0db09a3d6076c54db170c3209d175dffabb0 Mon Sep 17 00:00:00 2001 From: krateng Date: Sat, 9 Apr 2022 21:11:06 +0200 Subject: [PATCH 03/39] Moved supervisor to __main__ --- maloja/__main__.py | 22 ++++++++++++++++++++- maloja/proccontrol/supervisor.py | 33 -------------------------------- 2 files changed, 21 insertions(+), 34 deletions(-) delete mode 100644 maloja/proccontrol/supervisor.py diff --git a/maloja/__main__.py b/maloja/__main__.py index 72a9d1a..981ad26 100644 --- a/maloja/__main__.py +++ b/maloja/__main__.py @@ -7,6 +7,7 @@ from ipaddress import ip_address from doreah.control import mainfunction from doreah.io import col +from doreah.logging import log from . import __pkginfo__ as pkginfo from . import globalconf @@ -50,7 +51,7 @@ def start(): setup() try: #p = subprocess.Popen(["python3","-m","maloja.server"],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL) - sp = subprocess.Popen(["python3","-m","maloja.proccontrol.supervisor"],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL) + sp = subprocess.Popen(["python3","-m","maloja","supervisor"],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL) print(col["green"]("Maloja started!")) port = globalconf.malojaconfig["PORT"] @@ -93,6 +94,24 @@ def run_server(): from . import server server.run_server() +def run_supervisor(): + setproctitle("maloja_supervisor") + while True: + log("Maloja is not running, starting...",module="supervisor") + try: + process = subprocess.Popen( + ["python3", "-m", "maloja","run"], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) + except Exception as e: + log("Error starting Maloja: " + str(e),module="supervisor") + else: + try: + process.wait() + except Exception as e: + log("Maloja crashed: " + str(e),module="supervisor") + def debug(): os.environ["MALOJA_DEV_MODE"] = 'true' globalconf.malojaconfig.load_environment() @@ -117,6 +136,7 @@ def main(*args,**kwargs): "restart":restart, "stop":stop, "run":run_server, + "supervisor":run_supervisor, "debug":debug, "setup":onlysetup, # admin scripts diff --git a/maloja/proccontrol/supervisor.py b/maloja/proccontrol/supervisor.py deleted file mode 100644 index f1ab668..0000000 --- a/maloja/proccontrol/supervisor.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python3 -import os - -from ..globalconf import malojaconfig - -import subprocess -import setproctitle -import signal -from doreah.logging import log - - -from .control import getInstance - - -setproctitle.setproctitle("maloja_supervisor") - -def start(): - try: - return subprocess.Popen( - ["python3", "-m", "maloja","run"], - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, - ) - except e: - log("Error starting Maloja: " + str(e),module="supervisor") - - - -while True: - log("Maloja is not running, starting...",module="supervisor") - process = start() - - process.wait() From 24dfa41ad9614cad43cf1380ba89db782c7dd7c4 Mon Sep 17 00:00:00 2001 From: krateng Date: Sat, 9 Apr 2022 21:20:48 +0200 Subject: [PATCH 04/39] Moved profiler to new dev subpackage --- maloja/dev/__init__.py | 2 ++ maloja/{proccontrol => dev}/profiler.py | 3 +-- maloja/server.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 maloja/dev/__init__.py rename maloja/{proccontrol => dev}/profiler.py (99%) diff --git a/maloja/dev/__init__.py b/maloja/dev/__init__.py new file mode 100644 index 0000000..1220cb9 --- /dev/null +++ b/maloja/dev/__init__.py @@ -0,0 +1,2 @@ +### Subpackage that takes care of all things that concern the server process itself, +### e.g. analytics diff --git a/maloja/proccontrol/profiler.py b/maloja/dev/profiler.py similarity index 99% rename from maloja/proccontrol/profiler.py rename to maloja/dev/profiler.py index 3a98d35..ace1c1f 100644 --- a/maloja/proccontrol/profiler.py +++ b/maloja/dev/profiler.py @@ -2,7 +2,6 @@ import os import cProfile, pstats - from doreah.logging import log from doreah.timing import Clock @@ -23,7 +22,7 @@ def profile(func): profiler.enable() result = func(*args,**kwargs) profiler.disable() - + log(f"Executed {func.__name__} ({args}, {kwargs}) in {clock.stop():.2f}s",module="debug_performance") try: pstats.Stats(profiler).dump_stats(os.path.join(benchmarkfolder,f"{func.__name__}.stats")) diff --git a/maloja/server.py b/maloja/server.py index 7805152..f0bebef 100644 --- a/maloja/server.py +++ b/maloja/server.py @@ -25,7 +25,7 @@ from .jinjaenv.context import jinja_environment from .apis import init_apis, apikeystore -from .proccontrol.profiler import profile +from .dev.profiler import profile ###### From abde7e72c4ff7e6594de503bafb5a9873a9ee2fa Mon Sep 17 00:00:00 2001 From: krateng Date: Sat, 9 Apr 2022 21:24:48 +0200 Subject: [PATCH 05/39] Moved scrobble generation to dev package --- maloja/__main__.py | 3 ++- maloja/{proccontrol/tasks => dev}/generate.py | 7 ++++--- maloja/proccontrol/tasks/__init__.py | 1 - 3 files changed, 6 insertions(+), 5 deletions(-) rename maloja/{proccontrol/tasks => dev}/generate.py (97%) diff --git a/maloja/__main__.py b/maloja/__main__.py index 981ad26..b1bdf23 100644 --- a/maloja/__main__.py +++ b/maloja/__main__.py @@ -13,6 +13,7 @@ from . import __pkginfo__ as pkginfo from . import globalconf from .proccontrol import tasks from .setup import setup +from .dev import generate @@ -142,7 +143,7 @@ def main(*args,**kwargs): # admin scripts "import":tasks.import_scrobbles, # maloja import /x/y.csv "backup":tasks.backup, # maloja backup --targetfolder /x/y --include_images - "generate":tasks.generate, # maloja generate 400 + "generate":generate.generate_scrobbles, # maloja generate 400 "export":tasks.export, # maloja export # aux "info":print_info diff --git a/maloja/proccontrol/tasks/generate.py b/maloja/dev/generate.py similarity index 97% rename from maloja/proccontrol/tasks/generate.py rename to maloja/dev/generate.py index 225b6ce..0083f67 100644 --- a/maloja/proccontrol/tasks/generate.py +++ b/maloja/dev/generate.py @@ -1,5 +1,6 @@ import random import datetime + from doreah.io import ask @@ -66,10 +67,10 @@ def generate_track(): -def generate(n=200): +def generate_scrobbles(n=200): + + from ..database.sqldb import add_scrobbles - from ...database.sqldb import add_scrobbles - n = int(n) if ask("Generate random scrobbles?",default=False): diff --git a/maloja/proccontrol/tasks/__init__.py b/maloja/proccontrol/tasks/__init__.py index eda907d..cf2cd85 100644 --- a/maloja/proccontrol/tasks/__init__.py +++ b/maloja/proccontrol/tasks/__init__.py @@ -1,4 +1,3 @@ from .import_scrobbles import import_scrobbles from .backup import backup -from .generate import generate from .export import export # read that line out loud From 871b3d289d6433b9404298a2521be704ce7a3c04 Mon Sep 17 00:00:00 2001 From: krateng Date: Sat, 9 Apr 2022 21:39:04 +0200 Subject: [PATCH 06/39] Moved monkey patching and globalconf to subpackage --- maloja/__init__.py | 4 ++-- maloja/__main__.py | 16 ++++++++-------- maloja/apis/_apikeys.py | 2 +- maloja/apis/listenbrainz.py | 2 +- maloja/apis/native_v1.py | 2 +- maloja/cleanup.py | 2 +- maloja/database/__init__.py | 2 +- maloja/database/associated.py | 2 +- maloja/database/dbcache.py | 2 +- maloja/database/jinjaview.py | 2 +- maloja/database/sqldb.py | 2 +- maloja/dev/profiler.py | 2 +- maloja/images.py | 2 +- maloja/jinjaenv/context.py | 2 +- maloja/malojatime.py | 2 +- maloja/{globalconf.py => pkg_global/conf.py} | 2 +- maloja/{ => pkg_global}/monkey.py | 0 maloja/proccontrol/tasks/backup.py | 2 +- maloja/proccontrol/tasks/import_scrobbles.py | 2 +- maloja/server.py | 2 +- maloja/setup.py | 2 +- maloja/thirdparty/__init__.py | 2 +- maloja/upgrade.py | 2 +- 23 files changed, 30 insertions(+), 30 deletions(-) rename maloja/{globalconf.py => pkg_global/conf.py} (99%) rename maloja/{ => pkg_global}/monkey.py (100%) diff --git a/maloja/__init__.py b/maloja/__init__.py index ec1fd37..f43dd84 100644 --- a/maloja/__init__.py +++ b/maloja/__init__.py @@ -1,4 +1,4 @@ # monkey patching -from . import monkey +from .pkg_global import monkey # configuration before all else -from . import globalconf +from .pkg_global import conf diff --git a/maloja/__main__.py b/maloja/__main__.py index b1bdf23..c7a57b8 100644 --- a/maloja/__main__.py +++ b/maloja/__main__.py @@ -10,7 +10,7 @@ from doreah.io import col from doreah.logging import log from . import __pkginfo__ as pkginfo -from . import globalconf +from .pkg_global import conf from .proccontrol import tasks from .setup import setup from .dev import generate @@ -55,7 +55,7 @@ def start(): sp = subprocess.Popen(["python3","-m","maloja","supervisor"],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL) print(col["green"]("Maloja started!")) - port = globalconf.malojaconfig["PORT"] + port = conf.malojaconfig["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:") @@ -115,16 +115,16 @@ def run_supervisor(): def debug(): os.environ["MALOJA_DEV_MODE"] = 'true' - globalconf.malojaconfig.load_environment() + conf.malojaconfig.load_environment() direct() def print_info(): print_header_info() - print(col['lightblue']("Configuration Directory:"),globalconf.dir_settings['config']) - print(col['lightblue']("Data Directory: "),globalconf.dir_settings['state']) - print(col['lightblue']("Log Directory: "),globalconf.dir_settings['logs']) - print(col['lightblue']("Network: "),f"IPv{ip_address(globalconf.malojaconfig['host']).version}, Port {globalconf.malojaconfig['port']}") - print(col['lightblue']("Timezone: "),f"UTC{globalconf.malojaconfig['timezone']:+d}") + print(col['lightblue']("Configuration Directory:"),conf.dir_settings['config']) + print(col['lightblue']("Data Directory: "),conf.dir_settings['state']) + print(col['lightblue']("Log Directory: "),conf.dir_settings['logs']) + print(col['lightblue']("Network: "),f"IPv{ip_address(conf.malojaconfig['host']).version}, Port {conf.malojaconfig['port']}") + print(col['lightblue']("Timezone: "),f"UTC{conf.malojaconfig['timezone']:+d}") print() print() diff --git a/maloja/apis/_apikeys.py b/maloja/apis/_apikeys.py index cc49c92..fd4773e 100644 --- a/maloja/apis/_apikeys.py +++ b/maloja/apis/_apikeys.py @@ -4,7 +4,7 @@ from doreah.keystore import KeyStore from doreah.logging import log -from ..globalconf import data_dir +from ..pkg_global.conf import data_dir apikeystore = KeyStore(file=data_dir['clients']("apikeys.yml"),save_endpoint="/apis/mlj_1/apikeys") diff --git a/maloja/apis/listenbrainz.py b/maloja/apis/listenbrainz.py index 457573f..3ba5fa9 100644 --- a/maloja/apis/listenbrainz.py +++ b/maloja/apis/listenbrainz.py @@ -4,7 +4,7 @@ from .. import database import datetime from ._apikeys import apikeystore -from ..globalconf import malojaconfig +from ..pkg_global.conf import malojaconfig class Listenbrainz(APIHandler): diff --git a/maloja/apis/native_v1.py b/maloja/apis/native_v1.py index 6e5ccac..16cc27d 100644 --- a/maloja/apis/native_v1.py +++ b/maloja/apis/native_v1.py @@ -11,7 +11,7 @@ from nimrodel import Multi from .. import database -from ..globalconf import malojaconfig, data_dir +from ..pkg_global.conf import malojaconfig, data_dir diff --git a/maloja/cleanup.py b/maloja/cleanup.py index e94fdae..f8b6623 100644 --- a/maloja/cleanup.py +++ b/maloja/cleanup.py @@ -2,7 +2,7 @@ import re import os import csv -from .globalconf import data_dir, malojaconfig +from .pkg_global.conf import data_dir, malojaconfig # need to do this as a class so it can retain loaded settings from file # apparently this is not true diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index ac3ec86..61fc8bf 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -7,7 +7,7 @@ from .. import images from ..malojatime import register_scrobbletime, time_stamps, ranges, alltime from ..malojauri import uri_to_internal, internal_to_uri, compose_querystring from ..thirdparty import proxy_scrobble_all -from ..globalconf import data_dir, malojaconfig +from ..pkg_global.conf import data_dir, malojaconfig from ..apis import apikeystore #db from . import sqldb diff --git a/maloja/database/associated.py b/maloja/database/associated.py index 00f6a5f..69ccc61 100644 --- a/maloja/database/associated.py +++ b/maloja/database/associated.py @@ -8,7 +8,7 @@ import csv import os from . import sqldb -from ..globalconf import data_dir +from ..pkg_global.conf import data_dir def load_associated_rules(): diff --git a/maloja/database/dbcache.py b/maloja/database/dbcache.py index ed93eb2..1b35994 100644 --- a/maloja/database/dbcache.py +++ b/maloja/database/dbcache.py @@ -8,7 +8,7 @@ import json from doreah.regular import runhourly from doreah.logging import log -from ..globalconf import malojaconfig +from ..pkg_global.conf import malojaconfig HIGH_NUMBER = 1000000 diff --git a/maloja/database/jinjaview.py b/maloja/database/jinjaview.py index ab19e73..37518ca 100644 --- a/maloja/database/jinjaview.py +++ b/maloja/database/jinjaview.py @@ -3,7 +3,7 @@ from . sqldb import engine from .dbcache import serialize -from ..globalconf import malojaconfig +from ..pkg_global.conf import malojaconfig from doreah.logging import log diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index 629dc7c..7a2a7ac 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -5,7 +5,7 @@ import math from datetime import datetime from threading import Lock -from ..globalconf import data_dir +from ..pkg_global.conf import data_dir from .dbcache import cached_wrapper, cached_wrapper_individual from doreah.logging import log diff --git a/maloja/dev/profiler.py b/maloja/dev/profiler.py index ace1c1f..e1e041b 100644 --- a/maloja/dev/profiler.py +++ b/maloja/dev/profiler.py @@ -5,7 +5,7 @@ import cProfile, pstats from doreah.logging import log from doreah.timing import Clock -from ..globalconf import data_dir +from ..pkg_global.conf import data_dir profiler = cProfile.Profile() diff --git a/maloja/images.py b/maloja/images.py index ba399f7..99c40a4 100644 --- a/maloja/images.py +++ b/maloja/images.py @@ -1,4 +1,4 @@ -from .globalconf import data_dir, malojaconfig +from .pkg_global.conf import data_dir, malojaconfig from . import thirdparty from . import database diff --git a/maloja/jinjaenv/context.py b/maloja/jinjaenv/context.py index 48356e7..55e2f4e 100644 --- a/maloja/jinjaenv/context.py +++ b/maloja/jinjaenv/context.py @@ -1,5 +1,5 @@ from . import filters -from ..globalconf import malojaconfig +from ..pkg_global.conf import malojaconfig from .. import database, malojatime, images, malojauri, thirdparty, __pkginfo__ from ..database import jinjaview diff --git a/maloja/malojatime.py b/maloja/malojatime.py index 5be3c72..2a53527 100644 --- a/maloja/malojatime.py +++ b/maloja/malojatime.py @@ -3,7 +3,7 @@ from calendar import monthrange from os.path import commonprefix import math -from .globalconf import malojaconfig +from .pkg_global.conf import malojaconfig OFFSET = malojaconfig["TIMEZONE"] diff --git a/maloja/globalconf.py b/maloja/pkg_global/conf.py similarity index 99% rename from maloja/globalconf.py rename to maloja/pkg_global/conf.py index 938e542..6cf39fa 100644 --- a/maloja/globalconf.py +++ b/maloja/pkg_global/conf.py @@ -3,7 +3,7 @@ from doreah.configuration import Configuration from doreah.configuration import types as tp -from .__pkginfo__ import VERSION +from ..__pkginfo__ import VERSION diff --git a/maloja/monkey.py b/maloja/pkg_global/monkey.py similarity index 100% rename from maloja/monkey.py rename to maloja/pkg_global/monkey.py diff --git a/maloja/proccontrol/tasks/backup.py b/maloja/proccontrol/tasks/backup.py index 73f797b..dadacfc 100644 --- a/maloja/proccontrol/tasks/backup.py +++ b/maloja/proccontrol/tasks/backup.py @@ -2,7 +2,7 @@ import tarfile import time import glob import os -from ...globalconf import dir_settings +from ...pkg_global.conf import dir_settings from pathlib import PurePath from doreah.logging import log diff --git a/maloja/proccontrol/tasks/import_scrobbles.py b/maloja/proccontrol/tasks/import_scrobbles.py index fec1f83..6eb1b7e 100644 --- a/maloja/proccontrol/tasks/import_scrobbles.py +++ b/maloja/proccontrol/tasks/import_scrobbles.py @@ -4,7 +4,7 @@ import json, csv from doreah.io import col, ask, prompt from ...cleanup import * -from ...globalconf import data_dir +from ...pkg_global.conf import data_dir c = CleanerAgent() diff --git a/maloja/server.py b/maloja/server.py index f0bebef..9685148 100644 --- a/maloja/server.py +++ b/maloja/server.py @@ -20,7 +20,7 @@ from . import database from .database.jinjaview import JinjaDBConnection from .images import resolve_track_image, resolve_artist_image from .malojauri import uri_to_internal, remove_identical -from .globalconf import malojaconfig, data_dir +from .pkg_global.conf import malojaconfig, data_dir from .jinjaenv.context import jinja_environment from .apis import init_apis, apikeystore diff --git a/maloja/setup.py b/maloja/setup.py index beb6cd0..b74dbab 100644 --- a/maloja/setup.py +++ b/maloja/setup.py @@ -6,7 +6,7 @@ from distutils import dir_util from doreah.io import col, ask, prompt from doreah import auth -from .globalconf import data_dir, dir_settings, malojaconfig +from .pkg_global.conf import data_dir, dir_settings, malojaconfig diff --git a/maloja/thirdparty/__init__.py b/maloja/thirdparty/__init__.py index e38518e..311b076 100644 --- a/maloja/thirdparty/__init__.py +++ b/maloja/thirdparty/__init__.py @@ -13,7 +13,7 @@ import base64 from doreah.logging import log from threading import BoundedSemaphore -from ..globalconf import malojaconfig +from ..pkg_global.conf import malojaconfig from .. import database diff --git a/maloja/upgrade.py b/maloja/upgrade.py index 7dff80e..825b41c 100644 --- a/maloja/upgrade.py +++ b/maloja/upgrade.py @@ -7,7 +7,7 @@ import csv from doreah.logging import log from doreah.io import col -from .globalconf import data_dir, dir_settings +from .pkg_global.conf import data_dir, dir_settings from .apis import _apikeys From 98e1926613fe24c34da0c5b4a6cc03cd19918e69 Mon Sep 17 00:00:00 2001 From: krateng Date: Fri, 15 Apr 2022 18:14:44 +0200 Subject: [PATCH 07/39] Moved svg icon to jinja snippet --- maloja/web/jinja/abstracts/base.jinja | 6 +++--- maloja/web/jinja/icons/settings.jinja | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 maloja/web/jinja/icons/settings.jinja diff --git a/maloja/web/jinja/abstracts/base.jinja b/maloja/web/jinja/abstracts/base.jinja index 8e1645c..7074886 100644 --- a/maloja/web/jinja/abstracts/base.jinja +++ b/maloja/web/jinja/abstracts/base.jinja @@ -80,9 +80,9 @@ -
- -
+ + {% include 'icons/settings.jinja' %} + diff --git a/maloja/web/jinja/icons/settings.jinja b/maloja/web/jinja/icons/settings.jinja new file mode 100644 index 0000000..ea2e003 --- /dev/null +++ b/maloja/web/jinja/icons/settings.jinja @@ -0,0 +1,5 @@ +
+ + + +
From c33fcf1dc1e5c390856a50d902aa930e4ce2ff1e Mon Sep 17 00:00:00 2001 From: krateng Date: Fri, 15 Apr 2022 18:16:54 +0200 Subject: [PATCH 08/39] Added edit function to web interface --- maloja/web/jinja/artist.jinja | 3 ++- maloja/web/jinja/icons/edit.jinja | 12 ++++++++++ maloja/web/jinja/track.jinja | 2 +- maloja/web/static/css/maloja.css | 4 ++++ maloja/web/static/js/edit.js | 39 +++++++++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 maloja/web/jinja/icons/edit.jinja diff --git a/maloja/web/jinja/artist.jinja b/maloja/web/jinja/artist.jinja index f738c8b..244b9c9 100644 --- a/maloja/web/jinja/artist.jinja +++ b/maloja/web/jinja/artist.jinja @@ -47,7 +47,8 @@ {% endif %} -

{{ info.artist }}

+

{{ info.artist }}

+ {% if adminmode %}{% include 'icons/edit.jinja' %}{% endif %} {% if competes %}#{{ info.position }}{% endif %}
{% if competes and included %} diff --git a/maloja/web/jinja/icons/edit.jinja b/maloja/web/jinja/icons/edit.jinja new file mode 100644 index 0000000..8d3ee34 --- /dev/null +++ b/maloja/web/jinja/icons/edit.jinja @@ -0,0 +1,12 @@ + +
+ + + + + + +
diff --git a/maloja/web/jinja/track.jinja b/maloja/web/jinja/track.jinja index 03762c6..c3e3ce6 100644 --- a/maloja/web/jinja/track.jinja +++ b/maloja/web/jinja/track.jinja @@ -42,7 +42,7 @@ {{ links.links(track.artists) }}
-

{{ info.track.title }}

+

{{ info.track.title }}

{{ awards.certs(track) }} #{{ info.position }}
diff --git a/maloja/web/static/css/maloja.css b/maloja/web/static/css/maloja.css index 3056671..abf70aa 100644 --- a/maloja/web/static/css/maloja.css +++ b/maloja/web/static/css/maloja.css @@ -72,6 +72,10 @@ div#settingsicon { right:30px; top:30px; } +div#editicon { + height:20px; + width:20px; +} /** diff --git a/maloja/web/static/js/edit.js b/maloja/web/static/js/edit.js index 0a415ba..7f3d788 100644 --- a/maloja/web/static/js/edit.js +++ b/maloja/web/static/js/edit.js @@ -10,3 +10,42 @@ function deleteScrobble(id,element) { neo.xhttpreq("/apis/mlj_1/delete_scrobble",data={'timestamp':id},method="POST",callback=(()=>null),json=true); } + + +function selectAll(e) { + // https://stackoverflow.com/a/6150060/6651341 + var range = document.createRange(); + range.selectNodeContents(e); + var sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); +} + +function editEntity() { + var namefield = document.getElementById('main_entity_name'); + namefield.contentEditable = "plaintext-only"; + + // dont allow new lines, done on enter + namefield.addEventListener('keypress',function(e){ + if (e.which === 13) { + e.preventDefault(); + doneEditing(); + } + + }) + // emergency, not pretty because it will move cursor + namefield.addEventListener('input',function(e){ + if (namefield.innerHTML.includes("\n")) { + namefield.innerHTML = namefield.innerHTML.replace("\n",""); + } + + }) + + namefield.focus(); + selectAll(namefield); +} + +function doneEditing() { + var namefield = document.getElementById('main_entity_name'); + namefield.contentEditable = "false"; +} From 371e73ac9965c13f78c5ce648e2892481845c41b Mon Sep 17 00:00:00 2001 From: krateng Date: Fri, 15 Apr 2022 18:48:03 +0200 Subject: [PATCH 09/39] Implemented artist name editing --- maloja/apis/native_v1.py | 11 ++++++++++- maloja/database/__init__.py | 7 +++++++ maloja/database/dbcache.py | 4 ++-- maloja/database/sqldb.py | 13 +++++++++++++ maloja/web/jinja/artist.jinja | 5 ++++- maloja/web/static/js/edit.js | 15 +++++++++++++++ 6 files changed, 51 insertions(+), 4 deletions(-) diff --git a/maloja/apis/native_v1.py b/maloja/apis/native_v1.py index 099df87..6c4542a 100644 --- a/maloja/apis/native_v1.py +++ b/maloja/apis/native_v1.py @@ -515,4 +515,13 @@ def get_export(**keys): @authenticated_function(api=True) def delete_scrobble(timestamp): """Internal Use Only""" - database.remove_scrobble(timestamp) + return database.remove_scrobble(timestamp) + + +@api.post("edit_artist") +@authenticated_function(api=True) +def edit_artist(oldname,newname): + # we probably wanna pass the id to the web interface at some point + # but for now we just use the old name as identifer as it's always unique + """Internal Use Only""" + return database.change_artist_name(oldname,newname) diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index 1526f20..67462a9 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -137,6 +137,13 @@ def remove_scrobble(timestamp): result = sqldb.delete_scrobble(timestamp) dbcache.invalidate_caches(timestamp) +@waitfordb +def change_artist_name(oldname,newname): + log(f"Renaming {oldname} to {newname}") + id = sqldb.get_artist_id(oldname) + sqldb.edit_artist(id,newname) + dbcache.invalidate_entity_cache() + dbcache.invalidate_caches() diff --git a/maloja/database/dbcache.py b/maloja/database/dbcache.py index c31d130..c9e53e0 100644 --- a/maloja/database/dbcache.py +++ b/maloja/database/dbcache.py @@ -94,12 +94,12 @@ def cached_wrapper_individual(inner_func): return outer_func -def invalidate_caches(scrobbletime): +def invalidate_caches(scrobbletime=None): if malojaconfig['USE_GLOBAL_CACHE']: cleared, kept = 0, 0 for k in cache.keys(): # VERY BIG TODO: differentiate between None as in 'unlimited timerange' and None as in 'time doesnt matter here'! - if (k[3] is None or scrobbletime >= k[3]) and (k[4] is None or scrobbletime <= k[4]): + if scrobbletime is None or (k[3] is None or scrobbletime >= k[3]) and (k[4] is None or scrobbletime <= k[4]): cleared += 1 del cache[k] else: diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index 7a2a7ac..3b33afb 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -353,6 +353,19 @@ def get_artist_id(artistname,create_new=True,dbconn=None): return result.inserted_primary_key[0] +### Edit existing + +@connection_provider +def edit_artist(id,artistdict,dbconn=None): + dbentry = artist_dict_to_db(artistdict) + + op = DB['artists'].update().where( + DB['artists'].c.id==id + ).values( + **dbentry + ) + result = dbconn.execute(op) + diff --git a/maloja/web/jinja/artist.jinja b/maloja/web/jinja/artist.jinja index 244b9c9..a023f84 100644 --- a/maloja/web/jinja/artist.jinja +++ b/maloja/web/jinja/artist.jinja @@ -29,7 +29,9 @@ {% block content %} - + @@ -73,6 +75,7 @@ +

Top Tracks

diff --git a/maloja/web/static/js/edit.js b/maloja/web/static/js/edit.js index 7f3d788..8a40717 100644 --- a/maloja/web/static/js/edit.js +++ b/maloja/web/static/js/edit.js @@ -41,6 +41,12 @@ function editEntity() { }) + // manually clicking away + namefield.addEventListener('blur',function(e){ + doneEditing(); + + }) + namefield.focus(); selectAll(namefield); } @@ -48,4 +54,13 @@ function editEntity() { function doneEditing() { var namefield = document.getElementById('main_entity_name'); namefield.contentEditable = "false"; + newname = document.getElementById('main_entity_name').innerHTML; + + neo.xhttpreq( + "/apis/mlj_1/edit_artist", + data={'oldname':original_entity,'newname':newname}, + method="POST", + callback=(()=>window.location = "?artist=" + newname), + json=true + ); } From bccd88acd489c6dfbee4f40534a01767a15c5adf Mon Sep 17 00:00:00 2001 From: krateng Date: Fri, 15 Apr 2022 19:41:44 +0200 Subject: [PATCH 10/39] Implemented track title editing and refactored edit system --- maloja/apis/native_v1.py | 12 ++++++++---- maloja/database/__init__.py | 27 +++++++++++++++++++-------- maloja/database/sqldb.py | 10 ++++++++++ maloja/web/jinja/artist.jinja | 3 ++- maloja/web/jinja/track.jinja | 6 ++++++ maloja/web/static/js/edit.js | 18 +++++++++++++++--- 6 files changed, 60 insertions(+), 16 deletions(-) diff --git a/maloja/apis/native_v1.py b/maloja/apis/native_v1.py index 6c4542a..fe8d245 100644 --- a/maloja/apis/native_v1.py +++ b/maloja/apis/native_v1.py @@ -520,8 +520,12 @@ def delete_scrobble(timestamp): @api.post("edit_artist") @authenticated_function(api=True) -def edit_artist(oldname,newname): - # we probably wanna pass the id to the web interface at some point - # but for now we just use the old name as identifer as it's always unique +def edit_artist(id,name): """Internal Use Only""" - return database.change_artist_name(oldname,newname) + return database.edit_artist(id,name) + +@api.post("edit_track") +@authenticated_function(api=True) +def edit_track(id,title): + """Internal Use Only""" + return database.edit_track(id,{'title':title}) diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index 67462a9..adf5be3 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -138,13 +138,20 @@ def remove_scrobble(timestamp): dbcache.invalidate_caches(timestamp) @waitfordb -def change_artist_name(oldname,newname): - log(f"Renaming {oldname} to {newname}") - id = sqldb.get_artist_id(oldname) - sqldb.edit_artist(id,newname) +def edit_artist(id,artistinfo): + artist = sqldb.get_artist(id) + log(f"Renaming {artist} to {artistinfo}") + sqldb.edit_artist(id,artistinfo) dbcache.invalidate_entity_cache() dbcache.invalidate_caches() +@waitfordb +def edit_track(id,trackinfo): + track = sqldb.get_track(id) + log(f"Renaming {track['title']} to {trackinfo['title']}") + sqldb.edit_track(id,trackinfo) + dbcache.invalidate_entity_cache() + dbcache.invalidate_caches() @@ -280,7 +287,8 @@ def artist_info(dbconn=None,**keys): artist = keys.get('artist') - artist = sqldb.get_artist(sqldb.get_artist_id(artist,dbconn=dbconn),dbconn=dbconn) + artist_id = sqldb.get_artist_id(artist,dbconn=dbconn) + artist = sqldb.get_artist(artist_id,dbconn=dbconn) alltimecharts = get_charts_artists(timerange=alltime(),dbconn=dbconn) scrobbles = get_scrobbles_num(artist=artist,timerange=alltime(),dbconn=dbconn) #we cant take the scrobble number from the charts because that includes all countas scrobbles @@ -298,7 +306,8 @@ def artist_info(dbconn=None,**keys): "silver": [year for year in cached.medals_artists if artist in cached.medals_artists[year]['silver']], "bronze": [year for year in cached.medals_artists if artist in cached.medals_artists[year]['bronze']], }, - "topweeks":len([e for e in cached.weekly_topartists if e == artist]) + "topweeks":len([e for e in cached.weekly_topartists if e == artist]), + "id":artist_id } except: # if the artist isnt in the charts, they are not being credited and we @@ -316,7 +325,8 @@ def track_info(dbconn=None,**keys): track = keys.get('track') - track = sqldb.get_track(sqldb.get_track_id(track,dbconn=dbconn),dbconn=dbconn) + track_id = sqldb.get_track_id(track,dbconn=dbconn) + track = sqldb.get_track(track_id,dbconn=dbconn) alltimecharts = get_charts_tracks(timerange=alltime(),dbconn=dbconn) #scrobbles = get_scrobbles_num(track=track,timerange=alltime()) @@ -340,7 +350,8 @@ def track_info(dbconn=None,**keys): "bronze": [year for year in cached.medals_tracks if track in cached.medals_tracks[year]['bronze']], }, "certification":cert, - "topweeks":len([e for e in cached.weekly_toptracks if e == track]) + "topweeks":len([e for e in cached.weekly_toptracks if e == track]), + "id":track_id } diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index 3b33afb..b560d8f 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -366,6 +366,16 @@ def edit_artist(id,artistdict,dbconn=None): ) result = dbconn.execute(op) +@connection_provider +def edit_track(id,trackdict,dbconn=None): + dbentry = track_dict_to_db(trackdict) + + op = DB['tracks'].update().where( + DB['tracks'].c.id==id + ).values( + **dbentry + ) + result = dbconn.execute(op) diff --git a/maloja/web/jinja/artist.jinja b/maloja/web/jinja/artist.jinja index a023f84..07bd7ef 100644 --- a/maloja/web/jinja/artist.jinja +++ b/maloja/web/jinja/artist.jinja @@ -30,7 +30,8 @@ {% block content %} diff --git a/maloja/web/jinja/track.jinja b/maloja/web/jinja/track.jinja index c3e3ce6..49ef8b8 100644 --- a/maloja/web/jinja/track.jinja +++ b/maloja/web/jinja/track.jinja @@ -23,6 +23,11 @@ {% block content %} + + {% import 'partials/awards_track.jinja' as awards %} @@ -43,6 +48,7 @@ {{ links.links(track.artists) }}

{{ info.track.title }}

+ {% if adminmode %}{% include 'icons/edit.jinja' %}{% endif %} {{ awards.certs(track) }} #{{ info.position }}
diff --git a/maloja/web/static/js/edit.js b/maloja/web/static/js/edit.js index 8a40717..dbdf3b9 100644 --- a/maloja/web/static/js/edit.js +++ b/maloja/web/static/js/edit.js @@ -55,12 +55,24 @@ function doneEditing() { var namefield = document.getElementById('main_entity_name'); namefield.contentEditable = "false"; newname = document.getElementById('main_entity_name').innerHTML; + var searchParams = new URLSearchParams(window.location.search); + + if (entity_type == 'artist') { + var endpoint = "/apis/mlj_1/edit_artist"; + searchParams.set("artist", newname); + var payload = {'id':entity_id,'name':newname}; + } + else if (entity_type == 'track') { + var endpoint = "/apis/mlj_1/edit_track"; + searchParams.set("title", newname); + var payload = {'id':entity_id,'title':newname} + } neo.xhttpreq( - "/apis/mlj_1/edit_artist", - data={'oldname':original_entity,'newname':newname}, + endpoint, + data=payload, method="POST", - callback=(()=>window.location = "?artist=" + newname), + callback=(()=>window.location = "?" + searchParams.toString()), json=true ); } From f3f7dbd8ef23ee4b0f37fad5636ea8441f4cd8a2 Mon Sep 17 00:00:00 2001 From: krateng Date: Sat, 16 Apr 2022 02:17:14 +0200 Subject: [PATCH 11/39] Fixed double request when editing --- maloja/web/static/js/edit.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maloja/web/static/js/edit.js b/maloja/web/static/js/edit.js index dbdf3b9..a86c9ee 100644 --- a/maloja/web/static/js/edit.js +++ b/maloja/web/static/js/edit.js @@ -29,7 +29,7 @@ function editEntity() { namefield.addEventListener('keypress',function(e){ if (e.which === 13) { e.preventDefault(); - doneEditing(); + namefield.blur(); // this leads to below } }) @@ -41,7 +41,7 @@ function editEntity() { }) - // manually clicking away + // manually clicking away OR enter namefield.addEventListener('blur',function(e){ doneEditing(); From 6601920f69924304dc0198193c1857a87a5ee0fc Mon Sep 17 00:00:00 2001 From: krateng Date: Sat, 16 Apr 2022 02:17:43 +0200 Subject: [PATCH 12/39] Fixed entrypoint --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b51cec9..0c968f7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,7 @@ full = [ ] [project.scripts] -maloja = "maloja:main" +maloja = "maloja.__main__:main" [build-system] requires = ["flit_core >=3.2,<4"] From b806be6e025d9aa39f22913a896c2995688d4381 Mon Sep 17 00:00:00 2001 From: krateng Date: Sat, 16 Apr 2022 03:10:51 +0200 Subject: [PATCH 13/39] Cached stats now use IDs to survive renames --- maloja/database/__init__.py | 16 ++++++++-------- maloja/database/cached.py | 28 ++++++++++++++++------------ maloja/database/sqldb.py | 24 ++++++++++++++---------- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/maloja/database/__init__.py b/maloja/database/__init__.py index adf5be3..71fd883 100644 --- a/maloja/database/__init__.py +++ b/maloja/database/__init__.py @@ -302,11 +302,11 @@ def artist_info(dbconn=None,**keys): "position":position, "associated":others, "medals":{ - "gold": [year for year in cached.medals_artists if artist in cached.medals_artists[year]['gold']], - "silver": [year for year in cached.medals_artists if artist in cached.medals_artists[year]['silver']], - "bronze": [year for year in cached.medals_artists if artist in cached.medals_artists[year]['bronze']], + "gold": [year for year in cached.medals_artists if artist_id in cached.medals_artists[year]['gold']], + "silver": [year for year in cached.medals_artists if artist_id in cached.medals_artists[year]['silver']], + "bronze": [year for year in cached.medals_artists if artist_id in cached.medals_artists[year]['bronze']], }, - "topweeks":len([e for e in cached.weekly_topartists if e == artist]), + "topweeks":len([e for e in cached.weekly_topartists if e == artist_id]), "id":artist_id } except: @@ -345,12 +345,12 @@ def track_info(dbconn=None,**keys): "scrobbles":scrobbles, "position":position, "medals":{ - "gold": [year for year in cached.medals_tracks if track in cached.medals_tracks[year]['gold']], - "silver": [year for year in cached.medals_tracks if track in cached.medals_tracks[year]['silver']], - "bronze": [year for year in cached.medals_tracks if track in cached.medals_tracks[year]['bronze']], + "gold": [year for year in cached.medals_tracks if track_id in cached.medals_tracks[year]['gold']], + "silver": [year for year in cached.medals_tracks if track_id in cached.medals_tracks[year]['silver']], + "bronze": [year for year in cached.medals_tracks if track_id in cached.medals_tracks[year]['bronze']], }, "certification":cert, - "topweeks":len([e for e in cached.weekly_toptracks if e == track]), + "topweeks":len([e for e in cached.weekly_toptracks if e == track_id]), "id":track_id } diff --git a/maloja/database/cached.py b/maloja/database/cached.py index 7967665..43a719a 100644 --- a/maloja/database/cached.py +++ b/maloja/database/cached.py @@ -3,6 +3,7 @@ from doreah.regular import runyearly, rundaily from .. import database +from . import sqldb from .. import malojatime as mjt @@ -27,8 +28,9 @@ def update_medals(): for year in mjt.ranges(step="year"): if year == mjt.thisyear(): break - charts_artists = database.get_charts_artists(timerange=year) - charts_tracks = database.get_charts_tracks(timerange=year) + with sqldb.engine.begin() as conn: + charts_artists = sqldb.count_scrobbles_by_artist(since=year.first_stamp(),to=year.last_stamp(),resolve_ids=False,dbconn=conn) + charts_tracks = sqldb.count_scrobbles_by_track(since=year.first_stamp(),to=year.last_stamp(),resolve_ids=False,dbconn=conn) entry_artists = {'gold':[],'silver':[],'bronze':[]} entry_tracks = {'gold':[],'silver':[],'bronze':[]} @@ -36,18 +38,19 @@ def update_medals(): medals_tracks[year.desc()] = entry_tracks for entry in charts_artists: - if entry['rank'] == 1: entry_artists['gold'].append(entry['artist']) - elif entry['rank'] == 2: entry_artists['silver'].append(entry['artist']) - elif entry['rank'] == 3: entry_artists['bronze'].append(entry['artist']) + if entry['rank'] == 1: entry_artists['gold'].append(entry['artist_id']) + elif entry['rank'] == 2: entry_artists['silver'].append(entry['artist_id']) + elif entry['rank'] == 3: entry_artists['bronze'].append(entry['artist_id']) else: break for entry in charts_tracks: - if entry['rank'] == 1: entry_tracks['gold'].append(entry['track']) - elif entry['rank'] == 2: entry_tracks['silver'].append(entry['track']) - elif entry['rank'] == 3: entry_tracks['bronze'].append(entry['track']) + if entry['rank'] == 1: entry_tracks['gold'].append(entry['track_id']) + elif entry['rank'] == 2: entry_tracks['silver'].append(entry['track_id']) + elif entry['rank'] == 3: entry_tracks['bronze'].append(entry['track_id']) else: break + @rundaily def update_weekly(): @@ -58,12 +61,13 @@ def update_weekly(): for week in mjt.ranges(step="week"): if week == mjt.thisweek(): break - charts_artists = database.get_charts_artists(timerange=week) - charts_tracks = database.get_charts_tracks(timerange=week) + with sqldb.engine.begin() as conn: + charts_artists = sqldb.count_scrobbles_by_artist(since=week.first_stamp(),to=week.last_stamp(),resolve_ids=False,dbconn=conn) + charts_tracks = sqldb.count_scrobbles_by_track(since=week.first_stamp(),to=week.last_stamp(),resolve_ids=False,dbconn=conn) for entry in charts_artists: - if entry['rank'] == 1: weekly_topartists.append(entry['artist']) + if entry['rank'] == 1: weekly_topartists.append(entry['artist_id']) else: break for entry in charts_tracks: - if entry['rank'] == 1: weekly_toptracks.append(entry['track']) + if entry['rank'] == 1: weekly_toptracks.append(entry['track_id']) else: break diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index b560d8f..5423952 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -508,7 +508,7 @@ def get_tracks(dbconn=None): @cached_wrapper @connection_provider -def count_scrobbles_by_artist(since,to,dbconn=None): +def count_scrobbles_by_artist(since,to,resolve_ids=True,dbconn=None): jointable = sql.join( DB['scrobbles'], DB['trackartists'], @@ -536,16 +536,18 @@ def count_scrobbles_by_artist(since,to,dbconn=None): ).order_by(sql.desc('count')) result = dbconn.execute(op).all() - - counts = [row.count for row in result] - artists = get_artists_map([row.artist_id for row in result]) - result = [{'scrobbles':row.count,'artist':artists[row.artist_id]} for row in result] + if resolve_ids: + counts = [row.count for row in result] + artists = get_artists_map([row.artist_id for row in result]) + result = [{'scrobbles':row.count,'artist':artists[row.artist_id]} for row in result] + else: + result = [{'scrobbles':row.count,'artist_id':row.artist_id} for row in result] result = rank(result,key='scrobbles') return result @cached_wrapper @connection_provider -def count_scrobbles_by_track(since,to,dbconn=None): +def count_scrobbles_by_track(since,to,resolve_ids=True,dbconn=None): op = sql.select( @@ -557,10 +559,12 @@ def count_scrobbles_by_track(since,to,dbconn=None): ).group_by(DB['scrobbles'].c.track_id).order_by(sql.desc('count')) result = dbconn.execute(op).all() - - counts = [row.count for row in result] - tracks = get_tracks_map([row.track_id for row in result]) - result = [{'scrobbles':row.count,'track':tracks[row.track_id]} for row in result] + if resolve_ids: + counts = [row.count for row in result] + tracks = get_tracks_map([row.track_id for row in result]) + result = [{'scrobbles':row.count,'track':tracks[row.track_id]} for row in result] + else: + result = [{'scrobbles':row.count,'track_id':row.track_id} for row in result] result = rank(result,key='scrobbles') return result From fa2ce0c05f60233c539283d9078012424a30aab8 Mon Sep 17 00:00:00 2001 From: krateng Date: Sat, 16 Apr 2022 04:37:50 +0200 Subject: [PATCH 14/39] Reduced DB connections for cached stats --- maloja/database/cached.py | 53 ++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/maloja/database/cached.py b/maloja/database/cached.py index 43a719a..ea39a29 100644 --- a/maloja/database/cached.py +++ b/maloja/database/cached.py @@ -25,28 +25,28 @@ def update_medals(): medals_artists.clear() medals_tracks.clear() - for year in mjt.ranges(step="year"): - if year == mjt.thisyear(): break + with sqldb.engine.begin() as conn: + for year in mjt.ranges(step="year"): + if year == mjt.thisyear(): break - with sqldb.engine.begin() as conn: charts_artists = sqldb.count_scrobbles_by_artist(since=year.first_stamp(),to=year.last_stamp(),resolve_ids=False,dbconn=conn) charts_tracks = sqldb.count_scrobbles_by_track(since=year.first_stamp(),to=year.last_stamp(),resolve_ids=False,dbconn=conn) - entry_artists = {'gold':[],'silver':[],'bronze':[]} - entry_tracks = {'gold':[],'silver':[],'bronze':[]} - medals_artists[year.desc()] = entry_artists - medals_tracks[year.desc()] = entry_tracks + entry_artists = {'gold':[],'silver':[],'bronze':[]} + entry_tracks = {'gold':[],'silver':[],'bronze':[]} + medals_artists[year.desc()] = entry_artists + medals_tracks[year.desc()] = entry_tracks - for entry in charts_artists: - if entry['rank'] == 1: entry_artists['gold'].append(entry['artist_id']) - elif entry['rank'] == 2: entry_artists['silver'].append(entry['artist_id']) - elif entry['rank'] == 3: entry_artists['bronze'].append(entry['artist_id']) - else: break - for entry in charts_tracks: - if entry['rank'] == 1: entry_tracks['gold'].append(entry['track_id']) - elif entry['rank'] == 2: entry_tracks['silver'].append(entry['track_id']) - elif entry['rank'] == 3: entry_tracks['bronze'].append(entry['track_id']) - else: break + for entry in charts_artists: + if entry['rank'] == 1: entry_artists['gold'].append(entry['artist_id']) + elif entry['rank'] == 2: entry_artists['silver'].append(entry['artist_id']) + elif entry['rank'] == 3: entry_artists['bronze'].append(entry['artist_id']) + else: break + for entry in charts_tracks: + if entry['rank'] == 1: entry_tracks['gold'].append(entry['track_id']) + elif entry['rank'] == 2: entry_tracks['silver'].append(entry['track_id']) + elif entry['rank'] == 3: entry_tracks['bronze'].append(entry['track_id']) + else: break @@ -58,16 +58,17 @@ def update_weekly(): weekly_topartists.clear() weekly_toptracks.clear() - for week in mjt.ranges(step="week"): - if week == mjt.thisweek(): break + with sqldb.engine.begin() as conn: + for week in mjt.ranges(step="week"): + if week == mjt.thisweek(): break + - with sqldb.engine.begin() as conn: charts_artists = sqldb.count_scrobbles_by_artist(since=week.first_stamp(),to=week.last_stamp(),resolve_ids=False,dbconn=conn) charts_tracks = sqldb.count_scrobbles_by_track(since=week.first_stamp(),to=week.last_stamp(),resolve_ids=False,dbconn=conn) - for entry in charts_artists: - if entry['rank'] == 1: weekly_topartists.append(entry['artist_id']) - else: break - for entry in charts_tracks: - if entry['rank'] == 1: weekly_toptracks.append(entry['track_id']) - else: break + for entry in charts_artists: + if entry['rank'] == 1: weekly_topartists.append(entry['artist_id']) + else: break + for entry in charts_tracks: + if entry['rank'] == 1: weekly_toptracks.append(entry['track_id']) + else: break From 83e3157ad14f322ddd798f5df7ae8f0df73d14c9 Mon Sep 17 00:00:00 2001 From: krateng Date: Sun, 17 Apr 2022 15:15:29 +0200 Subject: [PATCH 15/39] Can now cancel editing --- maloja/web/jinja/artist.jinja | 2 ++ maloja/web/jinja/icons/edit.jinja | 1 - maloja/web/jinja/track.jinja | 2 ++ maloja/web/static/js/edit.js | 56 +++++++++++++++++++------------ 4 files changed, 39 insertions(+), 22 deletions(-) diff --git a/maloja/web/jinja/artist.jinja b/maloja/web/jinja/artist.jinja index 07bd7ef..f896ea8 100644 --- a/maloja/web/jinja/artist.jinja +++ b/maloja/web/jinja/artist.jinja @@ -6,6 +6,7 @@ {% block scripts %} + {% endblock %} {% set artist = filterkeys.artist %} @@ -32,6 +33,7 @@ diff --git a/maloja/web/jinja/icons/edit.jinja b/maloja/web/jinja/icons/edit.jinja index 8d3ee34..4ffb9f0 100644 --- a/maloja/web/jinja/icons/edit.jinja +++ b/maloja/web/jinja/icons/edit.jinja @@ -1,4 +1,3 @@ -
diff --git a/maloja/web/jinja/track.jinja b/maloja/web/jinja/track.jinja index 49ef8b8..17d79e9 100644 --- a/maloja/web/jinja/track.jinja +++ b/maloja/web/jinja/track.jinja @@ -5,6 +5,7 @@ {% block scripts %} +
+ + + + + + +
diff --git a/maloja/web/jinja/icons/merge_mark.jinja b/maloja/web/jinja/icons/merge_mark.jinja new file mode 100644 index 0000000..11f4bdb --- /dev/null +++ b/maloja/web/jinja/icons/merge_mark.jinja @@ -0,0 +1,5 @@ +
+ + + +
From 0d985ff706fc1c4f7f69ba3654d7cd6b022e4161 Mon Sep 17 00:00:00 2001 From: krateng Date: Sun, 17 Apr 2022 16:36:33 +0200 Subject: [PATCH 19/39] Reorganized admin mode icons --- maloja/web/jinja/abstracts/base.jinja | 6 ++++-- maloja/web/jinja/artist.jinja | 12 ++++++++++-- maloja/web/jinja/icons/edit.jinja | 2 +- maloja/web/jinja/icons/merge.jinja | 4 ++-- maloja/web/jinja/icons/merge_mark.jinja | 2 +- maloja/web/jinja/icons/settings.jinja | 6 ++++-- maloja/web/jinja/track.jinja | 9 ++++++++- maloja/web/static/css/maloja.css | 21 +++++++++++---------- maloja/web/static/js/edit.js | 1 + 9 files changed, 42 insertions(+), 21 deletions(-) diff --git a/maloja/web/jinja/abstracts/base.jinja b/maloja/web/jinja/abstracts/base.jinja index 7074886..bed8868 100644 --- a/maloja/web/jinja/abstracts/base.jinja +++ b/maloja/web/jinja/abstracts/base.jinja @@ -80,9 +80,11 @@
- + + diff --git a/maloja/web/jinja/artist.jinja b/maloja/web/jinja/artist.jinja index f896ea8..5675127 100644 --- a/maloja/web/jinja/artist.jinja +++ b/maloja/web/jinja/artist.jinja @@ -27,6 +27,13 @@ {% set encodedartist = mlj_uri.uriencode({'artist':artist}) %} +{% block icon_bar %} + {% if adminmode %} + {% include 'icons/edit.jinja' %} + {% include 'icons/merge.jinja' %} + {% include 'icons/merge_mark.jinja' %} + {% endif %} +{% endblock %} {% block content %} @@ -53,7 +60,6 @@

{{ info.artist }}

- {% if adminmode %}{% include 'icons/edit.jinja' %}{% endif %} {% if competes %}#{{ info.position }}{% endif %}
{% if competes and included %} @@ -62,7 +68,9 @@ Competing under {{ links.link(credited) }} (#{{ info.position }}) {% endif %} -

{{ info['scrobbles'] }} Scrobbles

+

+ {{ info['scrobbles'] }} Scrobbles +

diff --git a/maloja/web/jinja/icons/edit.jinja b/maloja/web/jinja/icons/edit.jinja index 4ffb9f0..6c76a60 100644 --- a/maloja/web/jinja/icons/edit.jinja +++ b/maloja/web/jinja/icons/edit.jinja @@ -1,5 +1,5 @@
- - +
+ diff --git a/maloja/web/jinja/icons/merge_mark.jinja b/maloja/web/jinja/icons/merge_mark.jinja index 11f4bdb..74bdad5 100644 --- a/maloja/web/jinja/icons/merge_mark.jinja +++ b/maloja/web/jinja/icons/merge_mark.jinja @@ -1,5 +1,5 @@
- +
diff --git a/maloja/web/jinja/icons/settings.jinja b/maloja/web/jinja/icons/settings.jinja index ea2e003..62434cc 100644 --- a/maloja/web/jinja/icons/settings.jinja +++ b/maloja/web/jinja/icons/settings.jinja @@ -1,5 +1,7 @@ -
- + +
+
+ diff --git a/maloja/web/jinja/track.jinja b/maloja/web/jinja/track.jinja index 17d79e9..dfc5815 100644 --- a/maloja/web/jinja/track.jinja +++ b/maloja/web/jinja/track.jinja @@ -22,6 +22,14 @@ {% set encodedtrack = mlj_uri.uriencode({'track':track}) %} +{% block icon_bar %} + {% if adminmode %} + {% include 'icons/edit.jinja' %} + {% include 'icons/merge.jinja' %} + {% include 'icons/merge_mark.jinja' %} + {% endif %} +{% endblock %} + {% block content %}
diff --git a/maloja/web/jinja/artist.jinja b/maloja/web/jinja/artist.jinja index 5675127..d8f4fbc 100644 --- a/maloja/web/jinja/artist.jinja +++ b/maloja/web/jinja/artist.jinja @@ -32,6 +32,7 @@ {% include 'icons/edit.jinja' %} {% include 'icons/merge.jinja' %} {% include 'icons/merge_mark.jinja' %} + {% include 'icons/merge_cancel.jinja' %} {% endif %} {% endblock %} diff --git a/maloja/web/jinja/icons/merge.jinja b/maloja/web/jinja/icons/merge.jinja index ff722fd..da65e8b 100644 --- a/maloja/web/jinja/icons/merge.jinja +++ b/maloja/web/jinja/icons/merge.jinja @@ -1,4 +1,4 @@ -
+
diff --git a/maloja/web/jinja/icons/merge_cancel.jinja b/maloja/web/jinja/icons/merge_cancel.jinja new file mode 100644 index 0000000..161d007 --- /dev/null +++ b/maloja/web/jinja/icons/merge_cancel.jinja @@ -0,0 +1,10 @@ +
+ + + + +
diff --git a/maloja/web/jinja/icons/merge_mark.jinja b/maloja/web/jinja/icons/merge_mark.jinja index 74bdad5..62deac8 100644 --- a/maloja/web/jinja/icons/merge_mark.jinja +++ b/maloja/web/jinja/icons/merge_mark.jinja @@ -1,4 +1,4 @@ -
+
diff --git a/maloja/web/jinja/track.jinja b/maloja/web/jinja/track.jinja index dfc5815..561dc68 100644 --- a/maloja/web/jinja/track.jinja +++ b/maloja/web/jinja/track.jinja @@ -27,6 +27,7 @@ {% include 'icons/edit.jinja' %} {% include 'icons/merge.jinja' %} {% include 'icons/merge_mark.jinja' %} + {% include 'icons/merge_cancel.jinja' %} {% endif %} {% endblock %} diff --git a/maloja/web/static/css/grisons.css b/maloja/web/static/css/grisons.css index 625b877..797fced 100644 --- a/maloja/web/static/css/grisons.css +++ b/maloja/web/static/css/grisons.css @@ -156,5 +156,5 @@ input:focus { .hide { - display:none; + display:none !important; } diff --git a/maloja/web/static/js/edit.js b/maloja/web/static/js/edit.js index b108fbb..d9c674a 100644 --- a/maloja/web/static/js/edit.js +++ b/maloja/web/static/js/edit.js @@ -108,6 +108,38 @@ function doneEditing() { // MERGING +function showValidMergeIcons() { + const lcst = window.sessionStorage; + var key = "marked_for_merge_" + entity_type; + var current_stored = (lcst.getItem(key) || '').split(","); + current_stored = current_stored.filter((x)=>x).map((x)=>parseInt(x)); + + var mergeicon = document.getElementById('mergeicon'); + var mergemarkicon = document.getElementById('mergemarkicon'); + var mergecancelicon = document.getElementById('mergecancelicon'); + + mergeicon.classList.add('hide'); + mergemarkicon.classList.add('hide'); + mergecancelicon.classList.add('hide'); + + if (current_stored.length == 0) { + mergemarkicon.classList.remove('hide'); + } + else { + mergecancelicon.classList.remove('hide'); + + if (current_stored.includes(entity_id)) { + + } + else { + mergemarkicon.classList.remove('hide'); + mergeicon.classList.remove('hide'); + } + } + +} + + function markForMerge() { const lcst = window.sessionStorage; var key = "marked_for_merge_" + entity_type; @@ -117,6 +149,7 @@ function markForMerge() { current_stored = [...new Set(current_stored)]; lcst.setItem(key,current_stored); //this already formats it correctly notify("Success","Marked " + entity_name + " for merge, currently " + current_stored.length + " marked!") + showValidMergeIcons(); } function merge() { @@ -147,3 +180,10 @@ function merge() { lcst.removeItem(key); } + +function cancelMerge() { + const lcst = window.sessionStorage; + var key = "marked_for_merge_" + entity_type; + lcst.setItem(key,[]); + showValidMergeIcons(); +} From 428d92a26786155bd49533dd73f6deeb32c3c7dd Mon Sep 17 00:00:00 2001 From: krateng Date: Thu, 21 Apr 2022 17:35:19 +0200 Subject: [PATCH 35/39] Updated release notes --- dev/releases/branch.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/releases/branch.yml b/dev/releases/branch.yml index 6fd8e81..8d3ef64 100644 --- a/dev/releases/branch.yml +++ b/dev/releases/branch.yml @@ -1,3 +1,4 @@ - "[Architecture] Cleaned up legacy process control" +- "[Architecture] Added proper exception framework to native API" - "[Feature] Implemented track title and artist name editing from web interface" - "[Feature] Implemented track and artist merging from web interface" From 8023c2d51c2f0b6f94ab97cfecee669f59894c46 Mon Sep 17 00:00:00 2001 From: krateng Date: Thu, 21 Apr 2022 17:59:42 +0200 Subject: [PATCH 36/39] Removed merge icon handling on pages that don't use them --- maloja/web/jinja/abstracts/base.jinja | 4 +--- maloja/web/jinja/artist.jinja | 1 + maloja/web/jinja/track.jinja | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/maloja/web/jinja/abstracts/base.jinja b/maloja/web/jinja/abstracts/base.jinja index b88b902..f0ff337 100644 --- a/maloja/web/jinja/abstracts/base.jinja +++ b/maloja/web/jinja/abstracts/base.jinja @@ -86,9 +86,7 @@ {% block icon_bar %}{% endblock %} {% include 'icons/settings.jinja' %}
- +
diff --git a/maloja/web/jinja/artist.jinja b/maloja/web/jinja/artist.jinja index d8f4fbc..eb09c77 100644 --- a/maloja/web/jinja/artist.jinja +++ b/maloja/web/jinja/artist.jinja @@ -33,6 +33,7 @@ {% include 'icons/merge.jinja' %} {% include 'icons/merge_mark.jinja' %} {% include 'icons/merge_cancel.jinja' %} + {% endif %} {% endblock %} diff --git a/maloja/web/jinja/track.jinja b/maloja/web/jinja/track.jinja index 561dc68..291add0 100644 --- a/maloja/web/jinja/track.jinja +++ b/maloja/web/jinja/track.jinja @@ -28,6 +28,7 @@ {% include 'icons/merge.jinja' %} {% include 'icons/merge_mark.jinja' %} {% include 'icons/merge_cancel.jinja' %} + {% endif %} {% endblock %} From 884e95dc58ea7fc7127d0cbf61482106ad5182f9 Mon Sep 17 00:00:00 2001 From: krateng Date: Thu, 21 Apr 2022 18:04:01 +0200 Subject: [PATCH 37/39] Manual scrobbling now also uses new notification system --- maloja/web/static/js/manualscrobble.js | 3 ++- maloja/web/static/js/notifications.js | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/maloja/web/static/js/manualscrobble.js b/maloja/web/static/js/manualscrobble.js index 1ae55de..4a58ee9 100644 --- a/maloja/web/static/js/manualscrobble.js +++ b/maloja/web/static/js/manualscrobble.js @@ -69,8 +69,9 @@ function scrobble(artists,title) { "title":title } + if (title != "" && artists.length > 0) { - neo.xhttpreq("/apis/mlj_1/newscrobble",data=payload,method="POST",callback=scrobbledone,json=true) + neo.xhttpreq("/apis/mlj_1/newscrobble",data=payload,method="POST",callback=notifyCallback,json=true) } document.getElementById("title").value = ""; diff --git a/maloja/web/static/js/notifications.js b/maloja/web/static/js/notifications.js index 54ad153..43e656f 100644 --- a/maloja/web/static/js/notifications.js +++ b/maloja/web/static/js/notifications.js @@ -38,14 +38,17 @@ function notifyCallback(request) { var body = request.response; var status = request.status; - if (status == 200) { var notification_type = 'info'; + var title = "Success!"; + var msg = "Scrobbled " + body.track.title + " by " + body.track.artists.join(", "); } else { var notification_type = 'warning'; + var title = "Error: " + body.error.type; + var msg = body.error.desc || ""; } - notify("Error: " + body.error.type,body.error.desc || "",notification_type); + notify(title,msg,notification_type); } From c0ff50b0643d184b4cd5d0a252c5d23754963d62 Mon Sep 17 00:00:00 2001 From: krateng Date: Thu, 21 Apr 2022 18:08:15 +0200 Subject: [PATCH 38/39] Updated admin mode information --- maloja/web/jinja/admin_overview.jinja | 2 ++ 1 file changed, 2 insertions(+) diff --git a/maloja/web/jinja/admin_overview.jinja b/maloja/web/jinja/admin_overview.jinja index 36993a6..cd6e2b9 100644 --- a/maloja/web/jinja/admin_overview.jinja +++ b/maloja/web/jinja/admin_overview.jinja @@ -66,6 +66,8 @@
  • manually scrobble from track pages
  • delete scrobbles
  • +
  • edit tracks and artists
  • +
  • merge tracks and artists
  • upload artist and track art by dropping a file on the existing image on an artist or track page
  • see more detailed error pages
From 91dae00851de9d06be31b03cd1c965948441fd63 Mon Sep 17 00:00:00 2001 From: krateng Date: Thu, 21 Apr 2022 18:19:33 +0200 Subject: [PATCH 39/39] Fixed renaming entities when new and old name are normalized the same --- maloja/database/sqldb.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/maloja/database/sqldb.py b/maloja/database/sqldb.py index 32860bd..9048297 100644 --- a/maloja/database/sqldb.py +++ b/maloja/database/sqldb.py @@ -369,8 +369,8 @@ def edit_artist(id,artistupdatedict,dbconn=None): dbentry = artist_dict_to_db(artistupdatedict) - existing_artist = get_artist_id(changedartist,create_new=False,dbconn=dbconn) - if existing_artist: + existing_artist_id = get_artist_id(changedartist,create_new=False,dbconn=dbconn) + if existing_artist_id not in (None,id): raise exc.ArtistExists(changedartist) op = DB['artists'].update().where( @@ -390,8 +390,8 @@ def edit_track(id,trackupdatedict,dbconn=None): dbentry = track_dict_to_db(trackupdatedict) - existing_track = get_track_id(changedtrack,create_new=False,dbconn=dbconn) - if existing_track: + existing_track_id = get_track_id(changedtrack,create_new=False,dbconn=dbconn) + if existing_track_id not in (None,id): raise exc.TrackExists(changedtrack) op = DB['tracks'].update().where(