mirror of
https://github.com/krateng/maloja.git
synced 2025-05-24 02:02:32 -04:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
c6cf28896c
@ -135,7 +135,7 @@ def debug():
|
|||||||
def print_info():
|
def print_info():
|
||||||
print_header_info()
|
print_header_info()
|
||||||
print(col['lightblue']("Configuration Directory:"),conf.dir_settings['config'])
|
print(col['lightblue']("Configuration Directory:"),conf.dir_settings['config'])
|
||||||
print(col['lightblue']("Data Directory: "),conf.dir_settings['state'])
|
print(col['lightblue']("State Directory: "),conf.dir_settings['state'])
|
||||||
print(col['lightblue']("Log Directory: "),conf.dir_settings['logs'])
|
print(col['lightblue']("Log Directory: "),conf.dir_settings['logs'])
|
||||||
print(col['lightblue']("Network: "),f"Dual Stack, Port {conf.malojaconfig['port']}" if conf.malojaconfig['host'] == "*" else f"IPv{ip_address(conf.malojaconfig['host']).version}, Port {conf.malojaconfig['port']}")
|
print(col['lightblue']("Network: "),f"Dual Stack, Port {conf.malojaconfig['port']}" if conf.malojaconfig['host'] == "*" else f"IPv{ip_address(conf.malojaconfig['host']).version}, Port {conf.malojaconfig['port']}")
|
||||||
print(col['lightblue']("Timezone: "),f"UTC{conf.malojaconfig['timezone']:+d}")
|
print(col['lightblue']("Timezone: "),f"UTC{conf.malojaconfig['timezone']:+d}")
|
||||||
|
@ -28,6 +28,15 @@ class Audioscrobbler(APIHandler):
|
|||||||
Exception: (500, {"error": 8, "message": "Operation failed"})
|
Exception: (500, {"error": 8, "message": "Operation failed"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# xml string escaping: https://stackoverflow.com/a/28703510
|
||||||
|
def xml_escape(self, str_xml: str):
|
||||||
|
str_xml = str_xml.replace("&", "&")
|
||||||
|
str_xml = str_xml.replace("<", "<")
|
||||||
|
str_xml = str_xml.replace("<", "<")
|
||||||
|
str_xml = str_xml.replace("\"", """)
|
||||||
|
str_xml = str_xml.replace("'", "'")
|
||||||
|
return str_xml
|
||||||
|
|
||||||
def get_method(self,pathnodes,keys):
|
def get_method(self,pathnodes,keys):
|
||||||
return keys.get("method")
|
return keys.get("method")
|
||||||
|
|
||||||
@ -45,12 +54,22 @@ class Audioscrobbler(APIHandler):
|
|||||||
token = keys.get("authToken")
|
token = keys.get("authToken")
|
||||||
user = keys.get("username")
|
user = keys.get("username")
|
||||||
password = keys.get("password")
|
password = keys.get("password")
|
||||||
|
format = keys.get("format") or "xml" # Audioscrobbler 2.0 uses XML by default
|
||||||
# either username and password
|
# either username and password
|
||||||
if user is not None and password is not None:
|
if user is not None and password is not None:
|
||||||
client = apikeystore.check_and_identify_key(password)
|
client = apikeystore.check_and_identify_key(password)
|
||||||
if client:
|
if client:
|
||||||
sessionkey = self.generate_key(client)
|
sessionkey = self.generate_key(client)
|
||||||
return 200,{"session":{"key":sessionkey}}
|
if format == "json":
|
||||||
|
return 200,{"session":{"key":sessionkey}}
|
||||||
|
else:
|
||||||
|
return 200,"""<lfm status="ok">
|
||||||
|
<session>
|
||||||
|
<name>%s</name>
|
||||||
|
<key>%s</key>
|
||||||
|
<subscriber>0</subscriber>
|
||||||
|
</session>
|
||||||
|
</lfm>""" % (self.xml_escape(user), self.xml_escape(sessionkey))
|
||||||
else:
|
else:
|
||||||
raise InvalidAuthException()
|
raise InvalidAuthException()
|
||||||
# or username and token (deprecated by lastfm)
|
# or username and token (deprecated by lastfm)
|
||||||
@ -59,7 +78,16 @@ class Audioscrobbler(APIHandler):
|
|||||||
key = apikeystore[client]
|
key = apikeystore[client]
|
||||||
if md5(user + md5(key)) == token:
|
if md5(user + md5(key)) == token:
|
||||||
sessionkey = self.generate_key(client)
|
sessionkey = self.generate_key(client)
|
||||||
return 200,{"session":{"key":sessionkey}}
|
if format == "json":
|
||||||
|
return 200,{"session":{"key":sessionkey}}
|
||||||
|
else:
|
||||||
|
return 200,"""<lfm status="ok">
|
||||||
|
<session>
|
||||||
|
<name>%s</name>
|
||||||
|
<key>%s</key>
|
||||||
|
<subscriber>0</subscriber>
|
||||||
|
</session>
|
||||||
|
</lfm>""" % (self.xml_escape(user), self.xml_escape(sessionkey))
|
||||||
raise InvalidAuthException()
|
raise InvalidAuthException()
|
||||||
else:
|
else:
|
||||||
raise BadAuthException()
|
raise BadAuthException()
|
||||||
|
@ -15,13 +15,15 @@ class CleanerAgent:
|
|||||||
def updateRules(self):
|
def updateRules(self):
|
||||||
|
|
||||||
rawrules = []
|
rawrules = []
|
||||||
for f in os.listdir(data_dir["rules"]()):
|
try:
|
||||||
if f.split('.')[-1].lower() != 'tsv': continue
|
for f in os.listdir(data_dir["rules"]()):
|
||||||
filepath = data_dir["rules"](f)
|
if f.split('.')[-1].lower() != 'tsv': continue
|
||||||
with open(filepath,'r') as filed:
|
filepath = data_dir["rules"](f)
|
||||||
reader = csv.reader(filed,delimiter="\t")
|
with open(filepath,'r') as filed:
|
||||||
rawrules += [[col for col in entry if col] for entry in reader if len(entry)>0 and not entry[0].startswith('#')]
|
reader = csv.reader(filed,delimiter="\t")
|
||||||
|
rawrules += [[col for col in entry if col] for entry in reader if len(entry)>0 and not entry[0].startswith('#')]
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
self.rules_belongtogether = [r[1] for r in rawrules if r[0]=="belongtogether"]
|
self.rules_belongtogether = [r[1] for r in rawrules if r[0]=="belongtogether"]
|
||||||
self.rules_notanartist = [r[1] for r in rawrules if r[0]=="notanartist"]
|
self.rules_notanartist = [r[1] for r in rawrules if r[0]=="notanartist"]
|
||||||
|
@ -19,12 +19,16 @@ def load_associated_rules():
|
|||||||
|
|
||||||
# load from file
|
# load from file
|
||||||
rawrules = []
|
rawrules = []
|
||||||
for f in os.listdir(data_dir["rules"]()):
|
try:
|
||||||
if f.split('.')[-1].lower() != 'tsv': continue
|
for f in os.listdir(data_dir["rules"]()):
|
||||||
filepath = data_dir["rules"](f)
|
if f.split('.')[-1].lower() != 'tsv': continue
|
||||||
with open(filepath,'r') as filed:
|
filepath = data_dir["rules"](f)
|
||||||
reader = csv.reader(filed,delimiter="\t")
|
with open(filepath,'r') as filed:
|
||||||
rawrules += [[col for col in entry if col] for entry in reader if len(entry)>0 and not entry[0].startswith('#')]
|
reader = csv.reader(filed,delimiter="\t")
|
||||||
|
rawrules += [[col for col in entry if col] for entry in reader if len(entry)>0 and not entry[0].startswith('#')]
|
||||||
|
except FileNotFoundError:
|
||||||
|
return
|
||||||
|
|
||||||
rules = [{'source_artist':r[1],'target_artist':r[2]} for r in rawrules if r[0]=="countas"]
|
rules = [{'source_artist':r[1],'target_artist':r[2]} for r in rawrules if r[0]=="countas"]
|
||||||
|
|
||||||
#for rule in rules:
|
#for rule in rules:
|
||||||
|
@ -311,6 +311,12 @@ data_directories = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for identifier,path in data_directories.items():
|
for identifier,path in data_directories.items():
|
||||||
|
if path is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if malojaconfig.readonly and (path == dir_settings['config'] or path.startswith(dir_settings['config']+'/')):
|
||||||
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
os.makedirs(path,exist_ok=True)
|
os.makedirs(path,exist_ok=True)
|
||||||
if not is_dir_usable(path): raise PermissionError(f"Directory {path} is not usable!")
|
if not is_dir_usable(path): raise PermissionError(f"Directory {path} is not usable!")
|
||||||
@ -321,17 +327,19 @@ for identifier,path in data_directories.items():
|
|||||||
print("Cannot use",path,"for cache, finding new folder...")
|
print("Cannot use",path,"for cache, finding new folder...")
|
||||||
data_directories['cache'] = dir_settings['cache'] = malojaconfig['DIRECTORY_CACHE'] = find_good_folder('cache')
|
data_directories['cache'] = dir_settings['cache'] = malojaconfig['DIRECTORY_CACHE'] = find_good_folder('cache')
|
||||||
else:
|
else:
|
||||||
print("Directory",path,"is not usable.")
|
print(f"Directory for {identifier} ({path}) is not writeable.")
|
||||||
print("Please change permissions or settings!")
|
print("Please change permissions or settings!")
|
||||||
print("Make sure Maloja has write and execute access to this directory.")
|
print("Make sure Maloja has write and execute access to this directory.")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
class DataDirs:
|
||||||
|
def __init__(self, dirs):
|
||||||
|
self.dirs = dirs
|
||||||
|
|
||||||
data_dir = {
|
def __getitem__(self, key):
|
||||||
k:lambda *x,k=k: pthj(data_directories[k],*x) for k in data_directories
|
return lambda *x, k=key: pthj(self.dirs[k], *x)
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
data_dir = DataDirs(data_directories)
|
||||||
|
|
||||||
### DOREAH OBJECTS
|
### DOREAH OBJECTS
|
||||||
|
|
||||||
@ -344,8 +352,10 @@ auth = doreah.auth.AuthManager(singleuser=True,cookieprefix='maloja',stylesheets
|
|||||||
doreah.logging.defaultlogger.logfolder = data_dir['logs']() if malojaconfig["LOGGING"] else None
|
doreah.logging.defaultlogger.logfolder = data_dir['logs']() if malojaconfig["LOGGING"] else None
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
custom_css_files = [f for f in os.listdir(data_dir['css']()) if f.lower().endswith('.css')]
|
custom_css_files = [f for f in os.listdir(data_dir['css']()) if f.lower().endswith('.css')]
|
||||||
|
except FileNotFoundError:
|
||||||
|
custom_css_files = []
|
||||||
|
|
||||||
from ..database.sqldb import set_maloja_info
|
from ..database.sqldb import set_maloja_info
|
||||||
set_maloja_info({'last_run_version':VERSION})
|
set_maloja_info({'last_run_version':VERSION})
|
||||||
|
@ -24,6 +24,12 @@ ext_apikeys = [
|
|||||||
def copy_initial_local_files():
|
def copy_initial_local_files():
|
||||||
with resources.files("maloja") / 'data_files' as folder:
|
with resources.files("maloja") / 'data_files' as folder:
|
||||||
for cat in dir_settings:
|
for cat in dir_settings:
|
||||||
|
if dir_settings[cat] is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if cat == 'config' and malojaconfig.readonly:
|
||||||
|
continue
|
||||||
|
|
||||||
distutils.dir_util.copy_tree(os.path.join(folder,cat),dir_settings[cat],update=False)
|
distutils.dir_util.copy_tree(os.path.join(folder,cat),dir_settings[cat],update=False)
|
||||||
|
|
||||||
charset = list(range(10)) + list("abcdefghijklmnopqrstuvwxyz") + list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
charset = list(range(10)) + list("abcdefghijklmnopqrstuvwxyz") + list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||||
@ -37,7 +43,6 @@ def setup():
|
|||||||
SKIP = malojaconfig["SKIP_SETUP"]
|
SKIP = malojaconfig["SKIP_SETUP"]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
print("Various external services can be used to display images. If not enough of them are set up, only local images will be used.")
|
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 ext_apikeys:
|
for k in ext_apikeys:
|
||||||
keyname = malojaconfig.get_setting_info(k)['name']
|
keyname = malojaconfig.get_setting_info(k)['name']
|
||||||
@ -45,6 +50,8 @@ def setup():
|
|||||||
if key is False:
|
if key is False:
|
||||||
print(f"\tCurrently not using a {col['red'](keyname)} for image display.")
|
print(f"\tCurrently not using a {col['red'](keyname)} for image display.")
|
||||||
elif key is None or key == "ASK":
|
elif key is None or key == "ASK":
|
||||||
|
if malojaconfig.readonly:
|
||||||
|
continue
|
||||||
promptmsg = f"\tPlease enter your {col['gold'](keyname)}. If you do not want to use one at this moment, simply leave this empty and press Enter."
|
promptmsg = f"\tPlease enter your {col['gold'](keyname)}. If you do not want to use one at this moment, simply leave this empty and press Enter."
|
||||||
key = prompt(promptmsg,types=(str,),default=False,skip=SKIP)
|
key = prompt(promptmsg,types=(str,),default=False,skip=SKIP)
|
||||||
malojaconfig[k] = key
|
malojaconfig[k] = key
|
||||||
|
Loading…
x
Reference in New Issue
Block a user