Files
igncore/core/setting_service.py
T
Minidodo 9f1da9a00d Fixed warnings caused by non-existing messagehub channels.
Changed the setting registration, removed the warnings.
Loot roll messages are more obvious now.
Superadmins are meant to stay mostily hidden, but are being exposed in !system again.
2021-08-29 17:54:18 +02:00

113 lines
4.0 KiB
Python

import inspect
from core.decorators import instance
from core.functions import get_attrs
from core.logger import Logger
from core.registry import Registry
@instance()
class SettingService:
def __init__(self):
self.logger = Logger(__name__)
self.settings = {}
self.db_cache = {}
self.change_listeners = {}
def inject(self, registry):
self.db = registry.get_instance("db")
self.bot = registry.get_instance("bot")
self.util = registry.get_instance("util")
def start(self):
# process decorators
for _, inst in Registry.get_all_instances().items():
for name, method in get_attrs(inst).items():
if hasattr(method, "setting"):
setting_name, value, description, extended_description, obj = getattr(method, "setting")
self.register(inst.module_name, setting_name, value, obj, description, extended_description)
def register(self, module, name, value, setting, description, extended_description=None):
"""Call during start"""
name = name.lower()
module = module.lower()
# do not generate settings for not loaded modules
if module.split(".")[0] not in self.bot.modules:
return
setting.set_name(name)
setting.set_description(description)
setting.set_extended_description(extended_description)
if not description:
self.logger.warning(f"No description specified for setting '{name}'")
if " " in name:
raise Exception(f"One or more spaces found in setting name '{name}' for module '{module}'")
row = self.db.query_single("SELECT name, value, description FROM setting WHERE name = ?", [name])
if row is None:
self.logger.debug(f"Adding setting '{name}'")
self.db.exec("INSERT INTO setting (name, value, description, module, verified) VALUES (?, ?, ?, ?, ?)",
[name, "", description, module, 1])
# verify default value is a valid value, and is formatted appropriately
setting.set_value(value)
else:
self.logger.debug(f"Updating setting '{name}'")
self.db.exec("UPDATE setting SET description = ?, verified = ?, module = ? WHERE name = ?",
[description, 1, module, name])
self.settings[name] = setting
def register_change_listener(self, setting_name, handler):
"""
Call during start
Args:
setting_name: str
handler: (name: string, old_value, new_value) -> void
"""
if len(inspect.signature(handler).parameters) != 3:
raise Exception(f"Incorrect number of arguments for handler '{handler.__module__}.{handler.__name__}()'")
if setting_name in self.settings:
if setting_name not in self.change_listeners:
self.change_listeners[setting_name] = []
self.change_listeners[setting_name].append(handler)
else:
raise Exception(f"Could not register change_listener for setting '{setting_name}' since it does not exist")
def get_value(self, name):
# check cache first
result = self.db_cache.get(name, None)
if result:
return result.value
else:
row = self.db.query_single("SELECT value FROM setting WHERE name = ?", [name])
# store result in cache
self.db_cache[name] = row
return row.value if row else None
def set_value(self, name, value):
old_value = self.get_value(name)
# clear cache
self.db_cache[name] = None
self.db.exec("UPDATE setting SET value = ? WHERE name = ?", [value, name])
if name in self.change_listeners:
for change_listener in self.change_listeners[name]:
change_listener(name, old_value, value)
def get(self, name):
name = name.lower()
setting = self.settings.get(name, None)
if setting:
return setting
else:
return None