diff --git a/kdb-bot/.cpl/schematic_db_table.py b/kdb-bot/.cpl/schematic_db_table.py new file mode 100644 index 00000000..4c01c549 --- /dev/null +++ b/kdb-bot/.cpl/schematic_db_table.py @@ -0,0 +1,100 @@ +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class DBTable(GenerateSchematicABC): + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + self._name = self._name.replace("_db_table", "") + self._class_name = self._class_name.split("Db_table")[0] + + def get_code(self) -> str: + import textwrap + + code = textwrap.dedent( + """\ + from datetime import datetime + + from cpl_core.database import TableABC + + + class $ClassName(TableABC): + def __init__( + self, + value: str, + created_at: datetime = None, + modified_at: datetime = None, + id=0, + ): + self._id = id + self._value = value + + TableABC.__init__(self) + self._created_at = created_at if created_at is not None else self._created_at + self._modified_at = modified_at if modified_at is not None else self._modified_at + + @property + def value(self) -> str: + return self._value + + @value.setter + def value(self, value: str): + self._value = value + + @staticmethod + def get_select_all_string() -> str: + return str( + f\""" + SELECT * FROM `$TableName`; + \""" + ) + + @staticmethod + def get_select_by_id_string(id: int) -> str: + return str( + f\""" + SELECT * FROM `$TableName` + WHERE `Id` = {id}; + \""" + ) + + @property + def insert_string(self) -> str: + return str( + f\""" + INSERT INTO `$TableName` ( + `Value` + ) VALUES ( + {self._value} + ); + \""" + ) + + @property + def udpate_string(self) -> str: + return str( + f\""" + UPDATE `$TableName` + SET `Value` = {self._value} + WHERE `Id` = {self._id}; + \""" + ) + + @property + def delete_string(self) -> str: + return str( + f\""" + DELETE FROM `$TableName` + WHERE `Id` = {self._id}; + \""" + ) + """ + ) + return self.build_code_str( + code, + ClassName=self._class_name, + TableName=self._class_name, + ) + + @classmethod + def register(cls): + GenerateSchematicABC.register(cls, "db-table", []) diff --git a/kdb-bot/.cpl/schematic_migration.py b/kdb-bot/.cpl/schematic_migration.py new file mode 100644 index 00000000..16c0fe5f --- /dev/null +++ b/kdb-bot/.cpl/schematic_migration.py @@ -0,0 +1,55 @@ +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class Migration(GenerateSchematicABC): + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + import textwrap + + code = textwrap.dedent( + """\ + from bot_core.logging.database_logger import DatabaseLogger + from bot_data.abc.migration_abc import MigrationABC + from bot_data.db_context import DBContext + + + class $ClassName(MigrationABC): + name = "1.0_$ClassName" + + def __init__(self, logger: DatabaseLogger, db: DBContext): + MigrationABC.__init__(self) + self._logger = logger + self._db = db + self._cursor = db.cursor + + def upgrade(self): + self._logger.debug(__name__, "Running upgrade") + + self._cursor.execute( + str( + f\""" + CREATE TABLE IF NOT EXISTS `$TableName` ( + `Id` BIGINT NOT NULL AUTO_INCREMENT, + `CreatedAt` DATETIME(6), + `LastModifiedAt` DATETIME(6), + PRIMARY KEY(`Id`) + ); + \""" + ) + ) + + def downgrade(self): + self._cursor.execute("DROP TABLE `$TableName`;") + """ + ) + return self.build_code_str( + code, + ClassName=self._class_name, + TableName=self._class_name.split("Migration")[0], + ) + + @classmethod + def register(cls): + GenerateSchematicABC.register(cls, "migration", []) diff --git a/kdb-bot/.cpl/schematic_query.py b/kdb-bot/.cpl/schematic_query.py index e34a3b6e..767cd77d 100644 --- a/kdb-bot/.cpl/schematic_query.py +++ b/kdb-bot/.cpl/schematic_query.py @@ -1,7 +1,7 @@ from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC -class query(GenerateSchematicABC): +class Query(GenerateSchematicABC): def __init__(self, *args: str): GenerateSchematicABC.__init__(self, *args) diff --git a/kdb-bot/cpl-workspace.json b/kdb-bot/cpl-workspace.json index c11fb4ac..451187dc 100644 --- a/kdb-bot/cpl-workspace.json +++ b/kdb-bot/cpl-workspace.json @@ -11,6 +11,7 @@ "auto-role": "src/modules/auto_role/auto-role.json", "base": "src/modules/base/base.json", "boot-log": "src/modules/boot_log/boot-log.json", + "config": "src/modules/config/modules/config.json", "database": "src/modules/database/database.json", "level": "src/modules/level/level.json", "permission": "src/modules/permission/permission.json", diff --git a/kdb-bot/src/bot/bot.json b/kdb-bot/src/bot/bot.json index 54f2ec06..34de4b9e 100644 --- a/kdb-bot/src/bot/bot.json +++ b/kdb-bot/src/bot/bot.json @@ -16,24 +16,25 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "cpl-core==2023.4.0.post2", + "cpl-core==2023.4.0.post5", "cpl-translation==2023.4.0.post1", "cpl-query==2023.4.0.post1", "cpl-discord==2023.4.0.post3", "Flask==2.3.2", "Flask-Classful==0.14.2", - "Flask-Cors==3.0.10", - "PyJWT==2.7.0", + "Flask-Cors==4.0.0", + "PyJWT==2.8.0", "waitress==2.1.2", "Flask-SocketIO==5.3.4", "eventlet==0.33.3", "requests-oauthlib==1.3.1", "icmplib==3.0.3", - "ariadne==0.19.1" + "ariadne==0.20.1", + "cryptography==41.0.2" ], "DevDependencies": [ "cpl-cli==2023.4.0.post3", - "pygount==1.5.1" + "pygount==1.6.1" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, diff --git a/kdb-bot/src/bot/config b/kdb-bot/src/bot/config index 440fb3bd..359f9c38 160000 --- a/kdb-bot/src/bot/config +++ b/kdb-bot/src/bot/config @@ -1 +1 @@ -Subproject commit 440fb3bd353dce31a2408c977a3168e3cfc32f9a +Subproject commit 359f9c38c3ec825a89f3bf289a65ec035cfcb693 diff --git a/kdb-bot/src/bot/extension/init_bot_extension.py b/kdb-bot/src/bot/extension/init_bot_extension.py index a4e0732a..04a4fcf0 100644 --- a/kdb-bot/src/bot/extension/init_bot_extension.py +++ b/kdb-bot/src/bot/extension/init_bot_extension.py @@ -3,7 +3,7 @@ from cpl_core.configuration import ConfigurationABC from cpl_core.dependency_injection import ServiceProviderABC from cpl_discord.service import DiscordBotServiceABC -from bot_core.configuration.bot_settings import BotSettings +from bot_data.model.technician_config import TechnicianConfig class InitBotExtension(ApplicationExtensionABC): @@ -11,6 +11,6 @@ class InitBotExtension(ApplicationExtensionABC): ApplicationExtensionABC.__init__(self) async def run(self, config: ConfigurationABC, services: ServiceProviderABC): - settings = config.get_configuration(BotSettings) + settings = config.get_configuration(TechnicianConfig) bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC, max_messages=settings.cache_max_messages) diff --git a/kdb-bot/src/bot/main.py b/kdb-bot/src/bot/main.py index 1b240eca..48b66eed 100644 --- a/kdb-bot/src/bot/main.py +++ b/kdb-bot/src/bot/main.py @@ -15,6 +15,7 @@ from bot.startup_settings_extension import StartupSettingsExtension from bot_api.app_api_extension import AppApiExtension from bot_core.core_extension.core_extension import CoreExtension from modules.boot_log.boot_log_extension import BootLogExtension +from modules.config.config_extension import ConfigExtension from modules.database.database_extension import DatabaseExtension @@ -30,6 +31,7 @@ class Program: .use_extension(StartupDiscordExtension) .use_extension(StartupModuleExtension) .use_extension(StartupMigrationExtension) + .use_extension(ConfigExtension) .use_extension(InitBotExtension) .use_extension(BootLogExtension) .use_extension(DatabaseExtension) diff --git a/kdb-bot/src/bot/module_list.py b/kdb-bot/src/bot/module_list.py index 7c6fb418..aee830ef 100644 --- a/kdb-bot/src/bot/module_list.py +++ b/kdb-bot/src/bot/module_list.py @@ -9,6 +9,7 @@ from modules.achievements.achievements_module import AchievementsModule from modules.auto_role.auto_role_module import AutoRoleModule from modules.base.base_module import BaseModule from modules.boot_log.boot_log_module import BootLogModule +from modules.config.config_module import ConfigModule from modules.database.database_module import DatabaseModule from modules.level.level_module import LevelModule from modules.permission.permission_module import PermissionModule @@ -24,9 +25,10 @@ class ModuleList: [ CoreModule, # has to be first! DataModule, + DatabaseModule, + ConfigModule, # has be to after db check GraphQLModule, PermissionModule, - DatabaseModule, AutoRoleModule, BaseModule, LevelModule, diff --git a/kdb-bot/src/bot/startup_migration_extension.py b/kdb-bot/src/bot/startup_migration_extension.py index a2d639fa..796b8257 100644 --- a/kdb-bot/src/bot/startup_migration_extension.py +++ b/kdb-bot/src/bot/startup_migration_extension.py @@ -9,6 +9,7 @@ from bot_data.migration.api_key_migration import ApiKeyMigration from bot_data.migration.api_migration import ApiMigration from bot_data.migration.auto_role_fix1_migration import AutoRoleFix1Migration from bot_data.migration.auto_role_migration import AutoRoleMigration +from bot_data.migration.config_migration import ConfigMigration from bot_data.migration.db_history_migration import DBHistoryMigration from bot_data.migration.initial_migration import InitialMigration from bot_data.migration.level_migration import LevelMigration @@ -44,3 +45,4 @@ class StartupMigrationExtension(StartupExtensionABC): services.add_transient(MigrationABC, UserWarningMigration) # 21.02.2023 #35 - 1.0.0 services.add_transient(MigrationABC, DBHistoryMigration) # 06.03.2023 #246 - 1.0.0 services.add_transient(MigrationABC, AchievementsMigration) # 14.06.2023 #268 - 1.1.0 + services.add_transient(MigrationABC, ConfigMigration) # 19.07.2023 #127 - 1.1.0 diff --git a/kdb-bot/src/bot/startup_settings_extension.py b/kdb-bot/src/bot/startup_settings_extension.py index 7a3dc599..caf34f19 100644 --- a/kdb-bot/src/bot/startup_settings_extension.py +++ b/kdb-bot/src/bot/startup_settings_extension.py @@ -1,6 +1,6 @@ import os from datetime import datetime -from typing import Callable, Type, Optional +from typing import Optional, Type, Callable from cpl_core.application import StartupExtensionABC from cpl_core.configuration import ConfigurationABC @@ -8,10 +8,6 @@ from cpl_core.dependency_injection import ServiceCollectionABC from cpl_core.environment import ApplicationEnvironmentABC from bot_core.configuration.bot_logging_settings import BotLoggingSettings -from bot_core.configuration.bot_settings import BotSettings -from modules.base.configuration.base_settings import BaseSettings -from modules.boot_log.configuration.boot_log_settings import BootLogSettings -from modules.permission.configuration.permission_settings import PermissionSettings class StartupSettingsExtension(StartupExtensionABC): @@ -33,12 +29,6 @@ class StartupSettingsExtension(StartupExtensionABC): configuration.add_json_file(f"config/feature-flags.{environment.host_name}.json", optional=True) configuration.add_configuration("Startup_StartTime", str(self._start_time)) - self._configure_settings_with_sub_settings(configuration, BotSettings, lambda x: x.servers, lambda x: x.id) - self._configure_settings_with_sub_settings(configuration, BaseSettings, lambda x: x.servers, lambda x: x.id) - self._configure_settings_with_sub_settings(configuration, BootLogSettings, lambda x: x.servers, lambda x: x.id) - self._configure_settings_with_sub_settings( - configuration, PermissionSettings, lambda x: x.servers, lambda x: x.id - ) self._configure_settings_with_sub_settings( configuration, BotLoggingSettings, lambda x: x.files, lambda x: x.key ) diff --git a/kdb-bot/src/bot_api/config b/kdb-bot/src/bot_api/config index c712f856..6d3f253f 160000 --- a/kdb-bot/src/bot_api/config +++ b/kdb-bot/src/bot_api/config @@ -1 +1 @@ -Subproject commit c712f856ebe30c71ac0b144045599ed2f91a1cba +Subproject commit 6d3f253f4121191308b4b0d5f01fa1c61b61406a diff --git a/kdb-bot/src/bot_api/configuration/api_settings.py b/kdb-bot/src/bot_api/configuration/api_settings.py index eb136f3b..62e0d71b 100644 --- a/kdb-bot/src/bot_api/configuration/api_settings.py +++ b/kdb-bot/src/bot_api/configuration/api_settings.py @@ -1,16 +1,13 @@ -import traceback - from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console class ApiSettings(ConfigurationModelABC): - def __init__(self): + def __init__(self, port: int = None, host: str = None, redirect_uri: bool = None): ConfigurationModelABC.__init__(self) - self._port = 80 - self._host = "" - self._redirect_to_https = False + self._port = 80 if port is None else port + self._host = "" if host is None else host + self._redirect_to_https = False if redirect_uri is None else redirect_uri @property def port(self) -> int: @@ -23,12 +20,3 @@ class ApiSettings(ConfigurationModelABC): @property def redirect_to_https(self) -> bool: return self._redirect_to_https - - def from_dict(self, settings: dict): - try: - self._port = int(settings["Port"]) - self._host = settings["Host"] - self._redirect_to_https = bool(settings["RedirectToHTTPS"]) - except Exception as e: - Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings") - Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") diff --git a/kdb-bot/src/bot_api/configuration/authentication_settings.py b/kdb-bot/src/bot_api/configuration/authentication_settings.py index 72f00c99..b9c3fff2 100644 --- a/kdb-bot/src/bot_api/configuration/authentication_settings.py +++ b/kdb-bot/src/bot_api/configuration/authentication_settings.py @@ -1,19 +1,22 @@ -import traceback -from datetime import datetime - from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console class AuthenticationSettings(ConfigurationModelABC): - def __init__(self): + def __init__( + self, + secret_key: str = None, + issuer: str = None, + audience: str = None, + token_expire_time: int = None, + refresh_token_expire_time: int = None, + ): ConfigurationModelABC.__init__(self) - self._secret_key = "" - self._issuer = "" - self._audience = "" - self._token_expire_time = 0 - self._refresh_token_expire_time = 0 + self._secret_key = "" if secret_key is None else secret_key + self._issuer = "" if issuer is None else issuer + self._audience = "" if audience is None else audience + self._token_expire_time = 0 if token_expire_time is None else token_expire_time + self._refresh_token_expire_time = 0 if refresh_token_expire_time is None else refresh_token_expire_time @property def secret_key(self) -> str: @@ -34,14 +37,3 @@ class AuthenticationSettings(ConfigurationModelABC): @property def refresh_token_expire_time(self) -> int: return self._refresh_token_expire_time - - def from_dict(self, settings: dict): - try: - self._secret_key = settings["SecretKey"] - self._issuer = settings["Issuer"] - self._audience = settings["Audience"] - self._token_expire_time = int(settings["TokenExpireTime"]) - self._refresh_token_expire_time = int(settings["RefreshTokenExpireTime"]) - except Exception as e: - Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings") - Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") diff --git a/kdb-bot/src/bot_api/configuration/discord_authentication_settings.py b/kdb-bot/src/bot_api/configuration/discord_authentication_settings.py index eaf76eec..8dcfbc84 100644 --- a/kdb-bot/src/bot_api/configuration/discord_authentication_settings.py +++ b/kdb-bot/src/bot_api/configuration/discord_authentication_settings.py @@ -1,19 +1,23 @@ -import traceback - from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console from cpl_query.extension import List class DiscordAuthenticationSettings(ConfigurationModelABC): - def __init__(self): + def __init__( + self, + client_secret: str = None, + redirect_uri: str = None, + scope: list = None, + token_url: str = None, + auth_url: str = None, + ): ConfigurationModelABC.__init__(self) - self._client_secret = "" - self._redirect_url = "" - self._scope = List() - self._token_url = "" - self._auth_url = "" + self._client_secret = "" if client_secret is None else client_secret + self._redirect_url = "" if redirect_uri is None else redirect_uri + self._scope = List() if scope is None else List(str, scope) + self._token_url = "" if token_url is None else token_url + self._auth_url = "" if auth_url is None else auth_url @property def client_secret(self) -> str: @@ -34,14 +38,3 @@ class DiscordAuthenticationSettings(ConfigurationModelABC): @property def auth_url(self) -> str: return self._auth_url - - def from_dict(self, settings: dict): - try: - self._client_secret = settings["ClientSecret"] - self._redirect_url = settings["RedirectURL"] - self._scope = List(str, settings["Scope"]) - self._token_url = settings["TokenURL"] - self._auth_url = settings["AuthURL"] - except Exception as e: - Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings") - Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") diff --git a/kdb-bot/src/bot_api/configuration/frontend_settings.py b/kdb-bot/src/bot_api/configuration/frontend_settings.py index da80ab6c..58c5aee1 100644 --- a/kdb-bot/src/bot_api/configuration/frontend_settings.py +++ b/kdb-bot/src/bot_api/configuration/frontend_settings.py @@ -1,22 +1,12 @@ -import traceback - from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console class FrontendSettings(ConfigurationModelABC): - def __init__(self): + def __init__(self, url: str = None): ConfigurationModelABC.__init__(self) - self._url = "" + self._url = "" if url is None else url @property def url(self) -> str: return self._url - - def from_dict(self, settings: dict): - try: - self._url = settings["URL"] - except Exception as e: - Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings") - Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") diff --git a/kdb-bot/src/bot_api/configuration/version_settings.py b/kdb-bot/src/bot_api/configuration/version_settings.py deleted file mode 100644 index c1439673..00000000 --- a/kdb-bot/src/bot_api/configuration/version_settings.py +++ /dev/null @@ -1,49 +0,0 @@ -from typing import Optional - -from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_cli.configuration.version_settings_name_enum import VersionSettingsNameEnum - - -class VersionSettings(ConfigurationModelABC): - def __init__(self, major: str = None, minor: str = None, micro: str = None): - ConfigurationModelABC.__init__(self) - - self._major: Optional[str] = major - self._minor: Optional[str] = minor - self._micro: Optional[str] = micro - - @property - def major(self) -> str: - return self._major - - @property - def minor(self) -> str: - return self._minor - - @property - def micro(self) -> str: - return self._micro - - def to_str(self) -> str: - if self._micro is None: - return f"{self._major}.{self._minor}" - else: - return f"{self._major}.{self._minor}.{self._micro}" - - def from_dict(self, settings: dict): - self._major = settings[VersionSettingsNameEnum.major.value] - self._minor = settings[VersionSettingsNameEnum.minor.value] - micro = settings[VersionSettingsNameEnum.micro.value] - if micro != "": - self._micro = micro - - def to_dict(self) -> dict: - version = { - VersionSettingsNameEnum.major.value: self._major, - VersionSettingsNameEnum.minor.value: self._minor, - } - - if self._micro is not None: - version[VersionSettingsNameEnum.micro.value] = self._micro - - return version diff --git a/kdb-bot/src/bot_core/abc/client_utils_abc.py b/kdb-bot/src/bot_core/abc/client_utils_abc.py index 6f393128..ecb67321 100644 --- a/kdb-bot/src/bot_core/abc/client_utils_abc.py +++ b/kdb-bot/src/bot_core/abc/client_utils_abc.py @@ -7,8 +7,8 @@ from cpl_query.extension import List from discord.ext.commands import Context from bot_data.model.auto_role_rule import AutoRoleRule +from bot_data.model.server_config import ServerConfig from bot_data.model.user import User -from modules.base.configuration.base_server_settings import BaseServerSettings class ClientUtilsABC(ABC): @@ -53,7 +53,7 @@ class ClientUtilsABC(ABC): self, created_at: datetime, user: User, - settings: BaseServerSettings, + settings: ServerConfig, is_reaction: bool = False, ) -> bool: pass diff --git a/kdb-bot/src/bot_core/configuration/bot_logging_settings.py b/kdb-bot/src/bot_core/configuration/bot_logging_settings.py index 1c0fb22a..81f4968f 100644 --- a/kdb-bot/src/bot_core/configuration/bot_logging_settings.py +++ b/kdb-bot/src/bot_core/configuration/bot_logging_settings.py @@ -6,12 +6,12 @@ from bot_core.configuration.file_logging_settings import FileLoggingSettings class BotLoggingSettings(ConfigurationModelABC): - def __init__(self, custom_logs: dict = None): + def __init__(self, **kwargs: dict): ConfigurationModelABC.__init__(self) self._files: List[FileLoggingSettings] = List(FileLoggingSettings) - if custom_logs is not None: - self._files_from_dict(custom_logs) + if kwargs is not None: + self._files_from_dict(kwargs) @property def files(self) -> List[FileLoggingSettings]: @@ -21,6 +21,5 @@ class BotLoggingSettings(ConfigurationModelABC): files = List(FileLoggingSettings) for s in settings: settings[s]["Key"] = s - st = JSONProcessor.process(FileLoggingSettings, settings[s]) - files.append(st) + files.append(JSONProcessor.process(FileLoggingSettings, settings[s])) self._files = files diff --git a/kdb-bot/src/bot_core/configuration/bot_settings.py b/kdb-bot/src/bot_core/configuration/bot_settings.py deleted file mode 100644 index dc6b8bbf..00000000 --- a/kdb-bot/src/bot_core/configuration/bot_settings.py +++ /dev/null @@ -1,79 +0,0 @@ -from cpl_core.configuration import ConfigurationModelABC -from cpl_query.extension import List - -from bot_api.json_processor import JSONProcessor -from bot_core.configuration.server_settings import ServerSettings - - -class BotSettings(ConfigurationModelABC): - def __init__( - self, - technicians: list = None, - wait_for_restart: int = 2, - wait_for_shutdown: int = 2, - cache_max_messages: int = 1000, - server_settings: dict = None, - ): - ConfigurationModelABC.__init__(self) - - self._technicians: List[int] = List(int) if technicians is None else technicians - self._wait_for_restart = wait_for_restart - self._wait_for_shutdown = wait_for_shutdown - self._cache_max_messages = cache_max_messages - - self._servers: List[ServerSettings] = List(ServerSettings) - - if server_settings is not None: - self._servers_from_dict(server_settings) - - @property - def servers(self) -> List[ServerSettings]: - return self._servers - - @property - def technicians(self) -> List[int]: - return self._technicians - - @property - def wait_for_restart(self) -> int: - return self._wait_for_restart - - @property - def wait_for_shutdown(self) -> int: - return self._wait_for_shutdown - - @property - def cache_max_messages(self) -> int: - return self._cache_max_messages - - def _servers_from_dict(self, settings: dict): - servers = List(ServerSettings) - for s in settings: - settings[s]["id"] = int(s) - st = JSONProcessor.process(ServerSettings, settings[s]) - servers.append(st) - self._servers = servers - - # def from_dict(self, settings: dict): - # try: - # self._technicians = settings["Technicians"] - # self._wait_for_restart = settings["WaitForRestart"] - # self._wait_for_shutdown = settings["WaitForShutdown"] - # settings.pop("Technicians") - # settings.pop("WaitForRestart") - # settings.pop("WaitForShutdown") - # - # if "CacheMaxMessages" in settings: - # self._cache_max_messages = settings["CacheMaxMessages"] - # settings.pop("CacheMaxMessages") - # - # servers = List(ServerSettings) - # for s in settings: - # st = ServerSettings() - # settings[s]["Id"] = s - # st.from_dict(settings[s]) - # servers.append(st) - # self._servers = servers - # except Exception as e: - # Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings") - # Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") diff --git a/kdb-bot/src/bot_core/configuration/feature_flags_enum.py b/kdb-bot/src/bot_core/configuration/feature_flags_enum.py index 37a579fe..9bd72c1f 100644 --- a/kdb-bot/src/bot_core/configuration/feature_flags_enum.py +++ b/kdb-bot/src/bot_core/configuration/feature_flags_enum.py @@ -16,6 +16,7 @@ class FeatureFlagsEnum(Enum): level_module = "LevelModule" moderator_module = "ModeratorModule" permission_module = "PermissionModule" + config_module = "ConfigModule" # features api_only = "ApiOnly" presence = "Presence" diff --git a/kdb-bot/src/bot_core/configuration/feature_flags_settings.py b/kdb-bot/src/bot_core/configuration/feature_flags_settings.py index b0d297b8..19aeb110 100644 --- a/kdb-bot/src/bot_core/configuration/feature_flags_settings.py +++ b/kdb-bot/src/bot_core/configuration/feature_flags_settings.py @@ -1,34 +1,38 @@ -import traceback - from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum class FeatureFlagsSettings(ConfigurationModelABC): - def __init__(self): + _flags = { + # modules + FeatureFlagsEnum.achievements_module.value: False, # 14.06.2023 #268 + FeatureFlagsEnum.api_module.value: False, # 13.10.2022 #70 + FeatureFlagsEnum.admin_module.value: False, # 02.10.2022 #48 + FeatureFlagsEnum.auto_role_module.value: True, # 03.10.2022 #54 + FeatureFlagsEnum.base_module.value: True, # 02.10.2022 #48 + FeatureFlagsEnum.boot_log_module.value: True, # 02.10.2022 #48 + FeatureFlagsEnum.core_module.value: True, # 03.10.2022 #56 + FeatureFlagsEnum.core_extension_module.value: True, # 03.10.2022 #56 + FeatureFlagsEnum.data_module.value: True, # 03.10.2022 #56 + FeatureFlagsEnum.database_module.value: True, # 02.10.2022 #48 + FeatureFlagsEnum.moderator_module.value: False, # 02.10.2022 #48 + FeatureFlagsEnum.permission_module.value: True, # 02.10.2022 #48 + FeatureFlagsEnum.config_module.value: True, # 19.07.2023 #127 + # features + FeatureFlagsEnum.api_only.value: False, # 13.10.2022 #70 + FeatureFlagsEnum.presence.value: True, # 03.10.2022 #56 + FeatureFlagsEnum.version_in_presence.value: False, # 21.03.2023 #253 + } + + def __init__(self, **kwargs: dict): ConfigurationModelABC.__init__(self) - self._flags = { - # modules - FeatureFlagsEnum.achievements_module.value: False, # 14.06.2023 #268 - FeatureFlagsEnum.api_module.value: False, # 13.10.2022 #70 - FeatureFlagsEnum.admin_module.value: False, # 02.10.2022 #48 - FeatureFlagsEnum.auto_role_module.value: True, # 03.10.2022 #54 - FeatureFlagsEnum.base_module.value: True, # 02.10.2022 #48 - FeatureFlagsEnum.boot_log_module.value: True, # 02.10.2022 #48 - FeatureFlagsEnum.core_module.value: True, # 03.10.2022 #56 - FeatureFlagsEnum.core_extension_module.value: True, # 03.10.2022 #56 - FeatureFlagsEnum.data_module.value: True, # 03.10.2022 #56 - FeatureFlagsEnum.database_module.value: True, # 02.10.2022 #48 - FeatureFlagsEnum.moderator_module.value: False, # 02.10.2022 #48 - FeatureFlagsEnum.permission_module.value: True, # 02.10.2022 #48 - # features - FeatureFlagsEnum.api_only.value: False, # 13.10.2022 #70 - FeatureFlagsEnum.presence.value: True, # 03.10.2022 #56 - FeatureFlagsEnum.version_in_presence.value: False, # 21.03.2023 #253 - } + if len(kwargs.keys()) == 0: + return + + for flag in [f.value for f in FeatureFlagsEnum]: + self._load_flag(kwargs, FeatureFlagsEnum(flag)) def get_flag(self, key: FeatureFlagsEnum) -> bool: if key.value not in self._flags: @@ -40,11 +44,3 @@ class FeatureFlagsSettings(ConfigurationModelABC): return self._flags[key.value] = bool(settings[key.value]) - - def from_dict(self, settings: dict): - try: - for flag in [f.value for f in FeatureFlagsEnum]: - self._load_flag(settings, FeatureFlagsEnum(flag)) - except Exception as e: - Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings") - Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") diff --git a/kdb-bot/src/bot_core/configuration/file_logging_settings.py b/kdb-bot/src/bot_core/configuration/file_logging_settings.py index b941601d..46028aa5 100644 --- a/kdb-bot/src/bot_core/configuration/file_logging_settings.py +++ b/kdb-bot/src/bot_core/configuration/file_logging_settings.py @@ -17,11 +17,3 @@ class FileLoggingSettings(LoggingSettings): @property def key(self) -> str: return self._key - - # def from_dict(self, settings: dict): - # try: - # self._key = settings["Key"] - # super().from_dict(settings) - # except Exception as e: - # Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings") - # Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") diff --git a/kdb-bot/src/bot_core/configuration/server_settings.py b/kdb-bot/src/bot_core/configuration/server_settings.py deleted file mode 100644 index ca382886..00000000 --- a/kdb-bot/src/bot_core/configuration/server_settings.py +++ /dev/null @@ -1,36 +0,0 @@ -from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC - - -class ServerSettings(ConfigurationModelABC): - def __init__( - self, - id: int = None, - message_delete_timer: int = None, - notification_chat_id: int = None, - ): - ConfigurationModelABC.__init__(self) - - self._id: int = id - self._message_delete_timer: int = message_delete_timer - self._notification_chat_id: int = notification_chat_id - - @property - def id(self) -> int: - return self._id - - @property - def message_delete_timer(self) -> int: - return self._message_delete_timer - - @property - def notification_chat_id(self) -> int: - return self._notification_chat_id - - # def from_dict(self, settings: dict): - # try: - # self._id = int(settings["Id"]) - # self._message_delete_timer = int(settings["MessageDeleteTimer"]) - # self._notification_chat_id = int(settings["NotificationChatId"]) - # except Exception as e: - # Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in settings") - # Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") diff --git a/kdb-bot/src/bot_core/service/client_utils_service.py b/kdb-bot/src/bot_core/service/client_utils_service.py index 01dafdda..104c5267 100644 --- a/kdb-bot/src/bot_core/service/client_utils_service.py +++ b/kdb-bot/src/bot_core/service/client_utils_service.py @@ -25,9 +25,9 @@ from bot_data.abc.user_message_count_per_hour_repository_abc import ( UserMessageCountPerHourRepositoryABC, ) from bot_data.model.auto_role_rule import AutoRoleRule +from bot_data.model.server_config import ServerConfig from bot_data.model.user import User from bot_data.model.user_message_count_per_hour import UserMessageCountPerHour -from modules.base.configuration.base_server_settings import BaseServerSettings class ClientUtilsService(ClientUtilsABC): @@ -139,7 +139,7 @@ class ClientUtilsService(ClientUtilsABC): self, created_at: datetime, user: User, - settings: BaseServerSettings, + settings: ServerConfig, is_reaction: bool = False, ) -> bool: umcph = None diff --git a/kdb-bot/src/bot_core/service/data_integrity_service.py b/kdb-bot/src/bot_core/service/data_integrity_service.py index 01f55653..923cf4cb 100644 --- a/kdb-bot/src/bot_core/service/data_integrity_service.py +++ b/kdb-bot/src/bot_core/service/data_integrity_service.py @@ -19,13 +19,13 @@ from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.model.client import Client from bot_data.model.known_user import KnownUser from bot_data.model.server import Server +from bot_data.model.server_config import ServerConfig from bot_data.model.user import User from bot_data.model.user_joined_server import UserJoinedServer from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel from bot_data.service.seeder_service import SeederService from bot_data.service.user_repository_service import ServerRepositoryABC from modules.achievements.achievement_service import AchievementService -from modules.base.configuration.base_server_settings import BaseServerSettings class DataIntegrityService: @@ -174,7 +174,7 @@ class DataIntegrityService: self._logger.warn(__name__, f"User not found in database: {u.id}") self._logger.debug(__name__, f"Add user: {u.id}") - self._users.add_user(User(u.id, 0, server)) + self._users.add_user(User(u.id, 0, 0, 0, server)) self._db_context.save_changes() self._logger.debug(__name__, f"Added User: {u.id}") @@ -255,7 +255,7 @@ class DataIntegrityService: self._logger.debug(__name__, f"Start checking UserJoinedVoiceChannel table") for guild in self._bot.guilds: guild: discord.Guild = guild - settings: BaseServerSettings = self._config.get_configuration(f"BaseServerSettings_{guild.id}") + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{guild.id}") server = self._servers.find_server_by_discord_id(guild.id) if server is None: @@ -347,7 +347,7 @@ class DataIntegrityService: f"Active UserJoinedGameServer found in database: {guild.id}:{member.id}@{join.joined_on}", ) join.leaved_on = datetime.now() - settings: BaseServerSettings = self._config.get_configuration(f"BaseServerSettings_{guild.id}") + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{guild.id}") if ( (join.leaved_on - join.joined_on).total_seconds() / 60 / 60 diff --git a/kdb-bot/src/bot_core/service/message_service.py b/kdb-bot/src/bot_core/service/message_service.py index 8b07cb79..71caa831 100644 --- a/kdb-bot/src/bot_core/service/message_service.py +++ b/kdb-bot/src/bot_core/service/message_service.py @@ -10,10 +10,10 @@ from discord import Interaction from discord.ext.commands import Context from bot_core.abc.message_service_abc import MessageServiceABC -from bot_core.configuration.server_settings import ServerSettings from bot_core.helper.log_message_helper import LogMessageHelper from bot_core.logging.message_logger import MessageLogger from bot_data.abc.client_repository_abc import ClientRepositoryABC +from bot_data.model.server_config import ServerConfig class MessageService(MessageServiceABC): @@ -33,7 +33,7 @@ class MessageService(MessageServiceABC): async def delete_messages(self, messages: List[discord.Message], guild_id: int, without_tracking=False): self._logger.debug(__name__, f"Try to delete {messages.count()} messages") - server_st: ServerSettings = self._config.get_configuration(f"ServerSettings_{guild_id}") + server_st: ServerConfig = self._config.get_configuration(f"ServerConfig_{guild_id}") await asyncio.sleep(server_st.message_delete_timer) for message in messages: await self.delete_message(message, mass_delete=True, without_tracking=without_tracking) @@ -50,7 +50,7 @@ class MessageService(MessageServiceABC): else None ) - server_st: ServerSettings = self._config.get_configuration(f"ServerSettings_{guild_id}") + server_st: ServerConfig = self._config.get_configuration(f"ServerConfig_{guild_id}") if not mass_delete: await asyncio.sleep(server_st.message_delete_timer) self._logger.debug( diff --git a/kdb-bot/src/bot_data/abc/data_seeder_abc.py b/kdb-bot/src/bot_data/abc/data_seeder_abc.py index e49dc486..1907f25e 100644 --- a/kdb-bot/src/bot_data/abc/data_seeder_abc.py +++ b/kdb-bot/src/bot_data/abc/data_seeder_abc.py @@ -7,5 +7,5 @@ class DataSeederABC(ABC): pass @abstractmethod - def seed(self): + async def seed(self): pass diff --git a/kdb-bot/src/bot_data/abc/server_config_repository_abc.py b/kdb-bot/src/bot_data/abc/server_config_repository_abc.py new file mode 100644 index 00000000..f66fdc89 --- /dev/null +++ b/kdb-bot/src/bot_data/abc/server_config_repository_abc.py @@ -0,0 +1,59 @@ +from abc import ABC, abstractmethod + +from bot_data.model.server_afk_channel_ids_config import ServerAFKChannelIdsConfig +from bot_data.model.server_config import ServerConfig +from bot_data.model.server_team_role_ids_config import ServerTeamRoleIdsConfig + + +class ServerConfigRepositoryABC(ABC): + @abstractmethod + def __init__(self): + pass + + @abstractmethod + def does_server_config_exists(self, server_id: int) -> bool: + pass + + @abstractmethod + def get_server_config_by_server(self, server_id: int) -> ServerConfig: + pass + + @abstractmethod + def get_server_config_by_id(self, config_id: int) -> ServerConfig: + pass + + @abstractmethod + def add_server_config(self, server_config: ServerConfig): + pass + + @abstractmethod + def update_server_config(self, server_config: ServerConfig): + pass + + @abstractmethod + def delete_server_config(self, server_config: ServerConfig): + pass + + @abstractmethod + def add_server_team_role_id_config(self, server_team_role_id: ServerTeamRoleIdsConfig): + pass + + @abstractmethod + def update_server_team_role_id_config(self, server_team_role_id: ServerTeamRoleIdsConfig): + pass + + @abstractmethod + def delete_server_team_role_id_config(self, server_team_role_id: ServerTeamRoleIdsConfig): + pass + + @abstractmethod + def add_server_afk_channel_config(self, server_afk_channel: ServerAFKChannelIdsConfig): + pass + + @abstractmethod + def update_server_afk_channel_config(self, server_afk_channel: ServerAFKChannelIdsConfig): + pass + + @abstractmethod + def delete_server_afk_channel_config(self, server_afk_channel: ServerAFKChannelIdsConfig): + pass diff --git a/kdb-bot/src/bot_data/abc/technician_config_repository_abc.py b/kdb-bot/src/bot_data/abc/technician_config_repository_abc.py new file mode 100644 index 00000000..25c88d96 --- /dev/null +++ b/kdb-bot/src/bot_data/abc/technician_config_repository_abc.py @@ -0,0 +1,55 @@ +from abc import ABC, abstractmethod + +from bot_data.model.technician_config import TechnicianConfig +from bot_data.model.technician_id_config import TechnicianIdConfig +from bot_data.model.technician_ping_url_config import TechnicianPingUrlConfig + + +class TechnicianConfigRepositoryABC(ABC): + @abstractmethod + def __init__(self): + pass + + @abstractmethod + def does_technician_config_exists(self) -> bool: + pass + + @abstractmethod + def get_technician_config(self) -> TechnicianConfig: + pass + + @abstractmethod + def add_technician_config(self, technician_config: TechnicianConfig): + pass + + @abstractmethod + def update_technician_config(self, technician_config: TechnicianConfig): + pass + + @abstractmethod + def delete_technician_config(self, technician_config: TechnicianConfig): + pass + + @abstractmethod + def add_technician_id_config(self, technician_id: TechnicianIdConfig): + pass + + @abstractmethod + def update_technician_id_config(self, technician_id: TechnicianIdConfig): + pass + + @abstractmethod + def delete_technician_id_config(self, technician_id: TechnicianIdConfig): + pass + + @abstractmethod + def add_technician_ping_url_config(self, technician_ping_url: TechnicianPingUrlConfig): + pass + + @abstractmethod + def update_technician_ping_url_config(self, technician_ping_url: TechnicianPingUrlConfig): + pass + + @abstractmethod + def delete_technician_ping_url_config(self, technician_ping_url: TechnicianPingUrlConfig): + pass diff --git a/kdb-bot/src/bot_data/data_module.py b/kdb-bot/src/bot_data/data_module.py index fd571abb..9c35713e 100644 --- a/kdb-bot/src/bot_data/data_module.py +++ b/kdb-bot/src/bot_data/data_module.py @@ -10,10 +10,13 @@ from bot_data.abc.api_key_repository_abc import ApiKeyRepositoryABC from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC from bot_data.abc.client_repository_abc import ClientRepositoryABC +from bot_data.abc.data_seeder_abc import DataSeederABC from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC from bot_data.abc.level_repository_abc import LevelRepositoryABC +from bot_data.abc.server_config_repository_abc import ServerConfigRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.technician_config_repository_abc import TechnicianConfigRepositoryABC from bot_data.abc.user_game_ident_repository_abc import UserGameIdentRepositoryABC from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC @@ -35,7 +38,11 @@ from bot_data.service.game_server_repository_service import GameServerRepository from bot_data.service.known_user_repository_service import KnownUserRepositoryService from bot_data.service.level_repository_service import LevelRepositoryService from bot_data.service.seeder_service import SeederService +from bot_data.service.server_config_repository_service import ServerConfigRepositoryService +from bot_data.service.server_config_seeder import ServerConfigSeeder from bot_data.service.server_repository_service import ServerRepositoryService +from bot_data.service.technician_config_repository_service import TechnicianConfigRepositoryService +from bot_data.service.technician_config_seeder import TechnicianConfigSeeder from bot_data.service.user_game_ident_repository_service import UserGameIdentRepositoryService from bot_data.service.user_joined_game_server_repository_service import UserJoinedGameServerRepositoryService from bot_data.service.user_joined_server_repository_service import ( @@ -80,5 +87,9 @@ class DataModule(ModuleABC): services.add_transient(GameServerRepositoryABC, GameServerRepositoryService) services.add_transient(UserGameIdentRepositoryABC, UserGameIdentRepositoryService) services.add_transient(AchievementRepositoryABC, AchievementRepositoryService) + services.add_transient(TechnicianConfigRepositoryABC, TechnicianConfigRepositoryService) + services.add_transient(ServerConfigRepositoryABC, ServerConfigRepositoryService) services.add_transient(SeederService) + services.add_transient(DataSeederABC, TechnicianConfigSeeder) + services.add_transient(DataSeederABC, ServerConfigSeeder) diff --git a/kdb-bot/src/bot_data/migration/config_migration.py b/kdb-bot/src/bot_data/migration/config_migration.py new file mode 100644 index 00000000..0370cbb4 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/config_migration.py @@ -0,0 +1,153 @@ +import os + +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.migration_abc import MigrationABC +from bot_data.db_context import DBContext + + +class ConfigMigration(MigrationABC): + name = "1.1.0_ConfigMigration" + + def __init__(self, logger: DatabaseLogger, db: DBContext): + MigrationABC.__init__(self) + self._logger = logger + self._db = db + self._cursor = db.cursor + + def _exec(self, file: str): + path = f"{os.path.dirname(os.path.realpath(__file__))}/db_history_scripts" + sql = open(f"{path}/{file}").read() + + for statement in sql.split("\n\n"): + self._cursor.execute(statement + ";") + + def upgrade(self): + self._logger.debug(__name__, "Running upgrade") + self._server_upgrade() + self._technician_upgrade() + + self._exec("config/server.sql") + self._exec("config/server_afk_channels.sql") + self._exec("config/server_team_roles.sql") + self._exec("config/technician.sql") + self._exec("config/technician_ids.sql") + self._exec("config/technician_ping_urls.sql") + + def _server_upgrade(self): + self._cursor.execute( + str( + f""" + CREATE TABLE IF NOT EXISTS `CFG_Server` ( + `Id` BIGINT NOT NULL AUTO_INCREMENT, + `MessageDeleteTimer` BIGINT NOT NULL DEFAULT 6, + `NotificationChatId` BIGINT NOT NULL, + `MaxVoiceStateHours` BIGINT NOT NULL DEFAULT 6, + `XpPerMessage` BIGINT NOT NULL DEFAULT 1, + `XpPerReaction` BIGINT NOT NULL DEFAULT 1, + `MaxMessageXpPerHour` BIGINT NOT NULL DEFAULT 20, + `XpPerOntimeHour` BIGINT NOT NULL DEFAULT 10, + `XpPerEventParticipation` BIGINT NOT NULL DEFAULT 10, + `XpPerAchievement` BIGINT NOT NULL DEFAULT 10, + `AFKCommandChannelId` BIGINT NOT NULL, + `HelpVoiceChannelId` BIGINT NOT NULL, + `TeamChannelId` BIGINT NOT NULL, + `LoginMessageChannelId` BIGINT NOT NULL, + `ServerId` BIGINT NOT NULL, + `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6), + `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + PRIMARY KEY(`Id`), + FOREIGN KEY (`ServerId`) REFERENCES `Servers`(`ServerId`) + ); + """ + ) + ) + + self._cursor.execute( + str( + f""" + CREATE TABLE IF NOT EXISTS `CFG_ServerAFKChannelIds` ( + `Id` BIGINT NOT NULL AUTO_INCREMENT, + `ChannelId` BIGINT NOT NULL, + `ServerId` BIGINT NOT NULL, + `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6), + `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + PRIMARY KEY(`Id`), + FOREIGN KEY (`ServerId`) REFERENCES `Servers`(`ServerId`) + ); + """ + ) + ) + + self._cursor.execute( + str( + f""" + CREATE TABLE IF NOT EXISTS `CFG_ServerTeamRoleIds` ( + `Id` BIGINT NOT NULL AUTO_INCREMENT, + `RoleId` BIGINT NOT NULL, + `TeamMemberType` ENUM('Moderator', 'Admin') NOT NULL, + `ServerId` BIGINT NOT NULL, + `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6), + `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + PRIMARY KEY(`Id`), + FOREIGN KEY (`ServerId`) REFERENCES `Servers`(`ServerId`) + ); + """ + ) + ) + + def _technician_upgrade(self): + self._cursor.execute( + str( + f""" + CREATE TABLE IF NOT EXISTS `CFG_Technician` ( + `Id` BIGINT NOT NULL AUTO_INCREMENT, + `HelpCommandReferenceUrl` VARCHAR(255) NOT NULL, + `WaitForRestart` BIGINT NOT NULL DEFAULT 8, + `WaitForShutdown` BIGINT NOT NULL DEFAULT 8, + `CacheMaxMessages` BIGINT NOT NULL DEFAULT 1000000, + `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6), + `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + PRIMARY KEY(`Id`) + ); + """ + ) + ) + + self._cursor.execute( + str( + f""" + CREATE TABLE IF NOT EXISTS `CFG_TechnicianPingUrls` ( + `Id` BIGINT NOT NULL AUTO_INCREMENT, + `URL` VARCHAR(255) NOT NULL, + `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6), + `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + PRIMARY KEY(`Id`) + ); + """ + ) + ) + + self._cursor.execute( + str( + f""" + CREATE TABLE IF NOT EXISTS `CFG_TechnicianIds` ( + `Id` BIGINT NOT NULL AUTO_INCREMENT, + `TechnicianId` BIGINT NOT NULL, + `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6), + `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + PRIMARY KEY(`Id`) + ); + """ + ) + ) + + def downgrade(self): + self._logger.debug(__name__, "Running downgrade") + + def _server_downgrade(self): + self._cursor.execute("DROP TABLE `CFG_Server`;") + + def _technician_downgrade(self): + self._cursor.execute("DROP TABLE `CFG_Technician`;") + self._cursor.execute("DROP TABLE `CFG_TechnicianPingUrls`;") + self._cursor.execute("DROP TABLE `CFG_TechnicianIds`;") diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/config/server.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/config/server.sql new file mode 100644 index 00000000..e9c327b8 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/config/server.sql @@ -0,0 +1,117 @@ +CREATE TABLE IF NOT EXISTS `CFG_ServerHistory` +( + `Id` BIGINT(20) NOT NULL, + `MessageDeleteTimer` BIGINT NOT NULL DEFAULT 6, + `NotificationChatId` BIGINT NOT NULL, + `MaxVoiceStateHours` BIGINT NOT NULL DEFAULT 6, + `XpPerMessage` BIGINT NOT NULL DEFAULT 1, + `XpPerReaction` BIGINT NOT NULL DEFAULT 1, + `MaxMessageXpPerHour` BIGINT NOT NULL DEFAULT 20, + `XpPerOntimeHour` BIGINT NOT NULL DEFAULT 10, + `XpPerEventParticipation` BIGINT NOT NULL DEFAULT 10, + `XpPerAchievement` BIGINT NOT NULL DEFAULT 10, + `AFKCommandChannelId` BIGINT NOT NULL, + `HelpVoiceChannelId` BIGINT NOT NULL, + `TeamChannelId` BIGINT NOT NULL, + `LoginMessageChannelId` BIGINT NOT NULL, + `ServerId` BIGINT NOT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_CFG_ServerUpdate`; + +CREATE TRIGGER `TR_CFG_ServerUpdate` + AFTER UPDATE + ON `CFG_Server` + FOR EACH ROW +BEGIN + INSERT INTO `CFG_ServerHistory` ( + `Id`, + `MessageDeleteTimer`, + `NotificationChatId`, + `MaxVoiceStateHours`, + `XpPerMessage`, + `XpPerReaction`, + `MaxMessageXpPerHour`, + `XpPerOntimeHour`, + `XpPerEventParticipation`, + `XpPerAchievement`, + `AFKCommandChannelId`, + `HelpVoiceChannelId`, + `TeamChannelId`, + `LoginMessageChannelId`, + `ServerId`, + `DateFrom`, + `DateTo` + ) + VALUES ( + OLD.Id, + OLD.MessageDeleteTimer, + OLD.NotificationChatId, + OLD.MaxVoiceStateHours, + OLD.XpPerMessage, + OLD.XpPerReaction, + OLD.MaxMessageXpPerHour, + OLD.XpPerOntimeHour, + OLD.XpPerEventParticipation, + OLD.XpPerAchievement, + OLD.AFKCommandChannelId, + OLD.HelpVoiceChannelId, + OLD.TeamChannelId, + OLD.LoginMessageChannelId, + OLD.ServerId, + OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_CFG_ServerDelete`; + +CREATE TRIGGER `TR_CFG_ServerDelete` + AFTER DELETE + ON `CFG_Server` + FOR EACH ROW +BEGIN + INSERT INTO `CFG_ServerHistory` ( + `Id`, + `MessageDeleteTimer`, + `NotificationChatId`, + `MaxVoiceStateHours`, + `XpPerMessage`, + `XpPerReaction`, + `MaxMessageXpPerHour`, + `XpPerOntimeHour`, + `XpPerEventParticipation`, + `XpPerAchievement`, + `AFKCommandChannelId`, + `HelpVoiceChannelId`, + `TeamChannelId`, + `LoginMessageChannelId`, + `ServerId`, + `Deleted`, + `DateFrom`, + `DateTo` + ) + VALUES ( + OLD.Id, + OLD.MessageDeleteTimer, + OLD.NotificationChatId, + OLD.MaxVoiceStateHours, + OLD.XpPerMessage, + OLD.XpPerReaction, + OLD.MaxMessageXpPerHour, + OLD.XpPerOntimeHour, + OLD.XpPerEventParticipation, + OLD.XpPerAchievement, + OLD.AFKCommandChannelId, + OLD.HelpVoiceChannelId, + OLD.TeamChannelId, + OLD.LoginMessageChannelId, + OLD.ServerId, + TRUE, + OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/config/server_afk_channels.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/config/server_afk_channels.sql new file mode 100644 index 00000000..4dfd7e31 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/config/server_afk_channels.sql @@ -0,0 +1,57 @@ +CREATE TABLE IF NOT EXISTS `CFG_ServerAFKChannelIdsHistory` +( + `Id` BIGINT(20) NOT NULL, + `ChannelId` BIGINT NOT NULL, + `ServerId` BIGINT NOT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_CFG_ServerAFKChannelIdsUpdate`; + +CREATE TRIGGER `TR_CFG_ServerAFKChannelIdsUpdate` + AFTER UPDATE + ON `CFG_ServerAFKChannelIds` + FOR EACH ROW +BEGIN + INSERT INTO `CFG_ServerAFKChannelIdsHistory` ( + `Id`, + `ChannelId`, + `ServerId`, + `DateFrom`, + `DateTo` + ) + VALUES ( + OLD.Id, + OLD.ChannelId, + OLD.ServerId, + OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_CFG_ServerAFKChannelIdsDelete`; + +CREATE TRIGGER `TR_CFG_ServerAFKChannelIdsDelete` + AFTER DELETE + ON `CFG_ServerAFKChannelIds` + FOR EACH ROW +BEGIN + INSERT INTO `CFG_ServerAFKChannelIdsHistory` ( + `Id`, + `ChannelId`, + `ServerId`, + `Deleted`, + `DateFrom`, + `DateTo` + ) + VALUES ( + OLD.Id, + OLD.ChannelId, + OLD.ServerId, + TRUE, + OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/config/server_team_roles.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/config/server_team_roles.sql new file mode 100644 index 00000000..8733da4d --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/config/server_team_roles.sql @@ -0,0 +1,62 @@ +CREATE TABLE IF NOT EXISTS `CFG_ServerTeamRoleIdsHistory` +( + `Id` BIGINT(20) NOT NULL, + `RoleId` BIGINT NOT NULL, + `TeamMemberType` ENUM('Moderator', 'Admin') NOT NULL, + `ServerId` BIGINT NOT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_CFG_ServerTeamRoleIdsUpdate`; + +CREATE TRIGGER `TR_CFG_ServerTeamRoleIdsUpdate` + AFTER UPDATE + ON `CFG_ServerTeamRoleIds` + FOR EACH ROW +BEGIN + INSERT INTO `CFG_ServerTeamRoleIdsHistory` ( + `Id`, + `RoleId`, + `TeamMemberType`, + `ServerId`, + `DateFrom`, + `DateTo` + ) + VALUES ( + OLD.Id, + OLD.RoleId, + OLD.TeamMemberType, + OLD.ServerId, + OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_CFG_ServerTeamRoleIdsDelete`; + +CREATE TRIGGER `TR_CFG_ServerTeamRoleIdsDelete` + AFTER DELETE + ON `CFG_ServerTeamRoleIds` + FOR EACH ROW +BEGIN + INSERT INTO `CFG_ServerTeamRoleIdsHistory` ( + `Id`, + `RoleId`, + `TeamMemberType`, + `ServerId`, + `Deleted`, + `DateFrom`, + `DateTo` + ) + VALUES ( + OLD.Id, + OLD.RoleId, + OLD.TeamMemberType, + OLD.ServerId, + TRUE, + OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/config/technician.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/config/technician.sql new file mode 100644 index 00000000..50907c2f --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/config/technician.sql @@ -0,0 +1,67 @@ +CREATE TABLE IF NOT EXISTS `CFG_TechnicianHistory` +( + `Id` BIGINT(20) NOT NULL, + `HelpCommandReferenceUrl` VARCHAR(255) NOT NULL, + `WaitForRestart` BIGINT NOT NULL DEFAULT 8, + `WaitForShutdown` BIGINT NOT NULL DEFAULT 8, + `CacheMaxMessages` BIGINT NOT NULL DEFAULT 1000000, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_CFG_TechnicianUpdate`; + +CREATE TRIGGER `TR_CFG_TechnicianUpdate` + AFTER UPDATE + ON `CFG_Technician` + FOR EACH ROW +BEGIN + INSERT INTO `CFG_TechnicianHistory` ( + `Id`, + `HelpCommandReferenceUrl`, + `WaitForRestart`, + `WaitForShutdown`, + `CacheMaxMessages`, + `DateFrom`, + `DateTo` + ) + VALUES ( + OLD.Id, + OLD.HelpCommandReferenceUrl, + OLD.WaitForRestart, + OLD.WaitForShutdown, + OLD.CacheMaxMessages, + OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_CFG_TechnicianDelete`; + +CREATE TRIGGER `TR_CFG_TechnicianDelete` + AFTER DELETE + ON `CFG_Technician` + FOR EACH ROW +BEGIN + INSERT INTO `CFG_TechnicianHistory` ( + `Id`, + `HelpCommandReferenceUrl`, + `WaitForRestart`, + `WaitForShutdown`, + `CacheMaxMessages`, + `Deleted`, + `DateFrom`, + `DateTo` + ) + VALUES ( + OLD.Id, + OLD.HelpCommandReferenceUrl, + OLD.WaitForRestart, + OLD.WaitForShutdown, + OLD.CacheMaxMessages, + TRUE, + OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/config/technician_ids.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/config/technician_ids.sql new file mode 100644 index 00000000..251d4b30 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/config/technician_ids.sql @@ -0,0 +1,52 @@ +CREATE TABLE IF NOT EXISTS `CFG_TechnicianIdsHistory` +( + `Id` BIGINT(20) NOT NULL, + `TechnicianId` BIGINT NOT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_CFG_TechnicianIdsUpdate`; + +CREATE TRIGGER `TR_CFG_TechnicianIdsUpdate` + AFTER UPDATE + ON `CFG_TechnicianIds` + FOR EACH ROW +BEGIN + INSERT INTO `CFG_TechnicianIdsHistory` ( + `Id`, + `TechnicianId`, + `DateFrom`, + `DateTo` + ) + VALUES ( + OLD.Id, + OLD.TechnicianId, + OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_CFG_TechnicianIdsDelete`; + +CREATE TRIGGER `TR_CFG_TechnicianIdsDelete` + AFTER DELETE + ON `CFG_TechnicianIds` + FOR EACH ROW +BEGIN + INSERT INTO `CFG_TechnicianIdsHistory` ( + `Id`, + `TechnicianId`, + `Deleted`, + `DateFrom`, + `DateTo` + ) + VALUES ( + OLD.Id, + OLD.TechnicianId, + TRUE, + OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/config/technician_ping_urls.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/config/technician_ping_urls.sql new file mode 100644 index 00000000..d61c3cce --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/config/technician_ping_urls.sql @@ -0,0 +1,52 @@ +CREATE TABLE IF NOT EXISTS `CFG_TechnicianPingUrlsHistory` +( + `Id` BIGINT(20) NOT NULL, + `URL` VARCHAR(255) NOT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_CFG_TechnicianPingUrlsUpdate`; + +CREATE TRIGGER `TR_CFG_TechnicianPingUrlsUpdate` + AFTER UPDATE + ON `CFG_TechnicianPingUrls` + FOR EACH ROW +BEGIN + INSERT INTO `CFG_TechnicianPingUrlsHistory` ( + `Id`, + `URL`, + `DateFrom`, + `DateTo` + ) + VALUES ( + OLD.Id, + OLD.URL, + OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_CFG_TechnicianPingUrlsDelete`; + +CREATE TRIGGER `TR_CFG_TechnicianPingUrlsDelete` + AFTER DELETE + ON `CFG_TechnicianPingUrls` + FOR EACH ROW +BEGIN + INSERT INTO `CFG_TechnicianPingUrlsHistory` ( + `Id`, + `URL`, + `Deleted`, + `DateFrom`, + `DateTo` + ) + VALUES ( + OLD.Id, + OLD.URL, + TRUE, + OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/model/server_afk_channel_ids_config.py b/kdb-bot/src/bot_data/model/server_afk_channel_ids_config.py new file mode 100644 index 00000000..9b182426 --- /dev/null +++ b/kdb-bot/src/bot_data/model/server_afk_channel_ids_config.py @@ -0,0 +1,85 @@ +from datetime import datetime + +from cpl_core.database import TableABC + + +class ServerAFKChannelIdsConfig(TableABC): + def __init__( + self, + channel_id: int, + server_id: int, + created_at: datetime = None, + modified_at: datetime = None, + id=0, + ): + self._id = id + self._channel_id = channel_id + self._server_id = server_id + + TableABC.__init__(self) + self._created_at = created_at if created_at is not None else self._created_at + self._modified_at = modified_at if modified_at is not None else self._modified_at + + @property + def channel_id(self) -> int: + return self._channel_id + + @staticmethod + def get_select_all_string() -> str: + return str( + f""" + SELECT * FROM `CFG_ServerAFKChannelIds`; + """ + ) + + @staticmethod + def get_select_by_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `CFG_ServerAFKChannelIds` + WHERE `Id` = {id}; + """ + ) + + @staticmethod + def get_select_by_server_id_string(server_id: int) -> str: + return str( + f""" + SELECT * FROM `CFG_ServerAFKChannelIds` + WHERE `ServerId` = {server_id}; + """ + ) + + @property + def insert_string(self) -> str: + return str( + f""" + INSERT INTO `CFG_ServerAFKChannelIds` ( + `ChannelId`, + `ServerId` + ) VALUES ( + {self._channel_id}, + {self._server_id} + ); + """ + ) + + @property + def udpate_string(self) -> str: + return str( + f""" + UPDATE `CFG_ServerAFKChannelIds` + SET `ChannelId` = {self._channel_id}, + `ServerId` = {self._server_id} + WHERE `Id` = {self._id}; + """ + ) + + @property + def delete_string(self) -> str: + return str( + f""" + DELETE FROM `CFG_ServerAFKChannelIds` + WHERE `ChannelId` = {self._channel_id}; + """ + ) diff --git a/kdb-bot/src/bot_data/model/server_config.py b/kdb-bot/src/bot_data/model/server_config.py new file mode 100644 index 00000000..ba1db9f6 --- /dev/null +++ b/kdb-bot/src/bot_data/model/server_config.py @@ -0,0 +1,278 @@ +from datetime import datetime + +from cpl_core.configuration import ConfigurationModelABC +from cpl_core.database import TableABC +from cpl_query.extension import List + +from bot_data.model.server import Server +from bot_data.model.server_team_role_ids_config import ServerTeamRoleIdsConfig + + +class ServerConfig(TableABC, ConfigurationModelABC): + def __init__( + self, + message_delete_timer: int, + notification_chat_id: int, + max_voice_state_hours: int, + xp_per_message: int, + xp_per_reaction: int, + max_message_xp_per_hour: int, + xp_per_ontime_hour: int, + xp_per_event_participation: int, + xp_per_achievement: int, + afk_command_channel_id: int, + help_voice_channel_id: int, + team_channel_id: int, + login_message_channel_id: int, + server: Server, + afk_channel_ids: List[int], + team_role_ids: List[ServerTeamRoleIdsConfig], + created_at: datetime = None, + modified_at: datetime = None, + id=0, + ): + self._id = id + self._message_delete_timer = message_delete_timer + self._notification_chat_id = notification_chat_id + self._max_voice_state_hours = max_voice_state_hours + self._xp_per_message = xp_per_message + self._xp_per_reaction = xp_per_reaction + self._max_message_xp_per_hour = max_message_xp_per_hour + self._xp_per_ontime_hour = xp_per_ontime_hour + self._xp_per_event_participation = xp_per_event_participation + self._xp_per_achievement = xp_per_achievement + self._afk_command_channel_id = afk_command_channel_id + self._help_voice_channel_id = help_voice_channel_id + self._team_channel_id = team_channel_id + self._login_message_channel_id = login_message_channel_id + self._server = server + self._afk_channel_ids = afk_channel_ids + self._team_role_ids = team_role_ids + + TableABC.__init__(self) + self._created_at = created_at if created_at is not None else self._created_at + self._modified_at = modified_at if modified_at is not None else self._modified_at + + @property + def id(self) -> int: + return self._id + + @property + def message_delete_timer(self) -> int: + return self._message_delete_timer + + @message_delete_timer.setter + def message_delete_timer(self, value: int): + self._message_delete_timer = value + + @property + def notification_chat_id(self) -> int: + return self._notification_chat_id + + @notification_chat_id.setter + def notification_chat_id(self, value: int): + self._notification_chat_id = value + + @property + def max_voice_state_hours(self) -> int: + return self._max_voice_state_hours + + @max_voice_state_hours.setter + def max_voice_state_hours(self, value: int): + self._max_voice_state_hours = value + + @property + def xp_per_message(self) -> int: + return self._xp_per_message + + @xp_per_message.setter + def xp_per_message(self, value: int): + self._xp_per_message = value + + @property + def xp_per_reaction(self) -> int: + return self._xp_per_reaction + + @xp_per_reaction.setter + def xp_per_reaction(self, value: int): + self._xp_per_reaction = value + + @property + def max_message_xp_per_hour(self) -> int: + return self._max_message_xp_per_hour + + @max_message_xp_per_hour.setter + def max_message_xp_per_hour(self, value: int): + self._max_message_xp_per_hour = value + + @property + def xp_per_ontime_hour(self) -> int: + return self._xp_per_ontime_hour + + @xp_per_ontime_hour.setter + def xp_per_ontime_hour(self, value: int): + self._xp_per_ontime_hour = value + + @property + def xp_per_event_participation(self) -> int: + return self._xp_per_event_participation + + @xp_per_event_participation.setter + def xp_per_event_participation(self, value: int): + self._xp_per_event_participation = value + + @property + def xp_per_achievement(self) -> int: + return self._xp_per_achievement + + @xp_per_achievement.setter + def xp_per_achievement(self, value: int): + self._xp_per_achievement = value + + @property + def afk_command_channel_id(self) -> int: + return self._afk_command_channel_id + + @afk_command_channel_id.setter + def afk_command_channel_id(self, value: int): + self._afk_command_channel_id = value + + @property + def help_voice_channel_id(self) -> int: + return self._help_voice_channel_id + + @help_voice_channel_id.setter + def help_voice_channel_id(self, value: int): + self._help_voice_channel_id = value + + @property + def team_channel_id(self) -> int: + return self._team_channel_id + + @team_channel_id.setter + def team_channel_id(self, value: int): + self._team_channel_id = value + + @property + def login_message_channel_id(self) -> int: + return self._login_message_channel_id + + @login_message_channel_id.setter + def login_message_channel_id(self, value: int): + self._login_message_channel_id = value + + @property + def afk_channel_ids(self) -> List[int]: + return self._afk_channel_ids + + @afk_channel_ids.setter + def afk_channel_ids(self, value: List[int]): + self._afk_channel_ids = value + + @property + def team_role_ids(self) -> List[ServerTeamRoleIdsConfig]: + return self._team_role_ids + + @team_role_ids.setter + def team_role_ids(self, value: List[ServerTeamRoleIdsConfig]): + self._team_role_ids = value + + @property + def server(self) -> Server: + return self._server + + @staticmethod + def get_select_all_string() -> str: + return str( + f""" + SELECT * FROM `CFG_Server`; + """ + ) + + @staticmethod + def get_select_by_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `CFG_Server` + WHERE `Id` = {id}; + """ + ) + + @staticmethod + def get_select_by_server_id_string(server_id: int) -> str: + return str( + f""" + SELECT * FROM `CFG_Server` + WHERE `ServerId` = {server_id}; + """ + ) + + @property + def insert_string(self) -> str: + return str( + f""" + INSERT INTO `CFG_Server` ( + `MessageDeleteTimer`, + `NotificationChatId`, + `MaxVoiceStateHours`, + `XpPerMessage`, + `XpPerReaction`, + `MaxMessageXpPerHour`, + `XpPerOntimeHour`, + `XpPerEventParticipation`, + `XpPerAchievement`, + `AFKCommandChannelId`, + `HelpVoiceChannelId`, + `TeamChannelId`, + `LoginMessageChannelId`, + `ServerId` + ) VALUES ( + {self._message_delete_timer}, + {self._notification_chat_id}, + {self._max_voice_state_hours}, + {self._xp_per_message}, + {self._xp_per_reaction}, + {self._max_message_xp_per_hour}, + {self._xp_per_ontime_hour}, + {self._xp_per_event_participation}, + {self._xp_per_achievement}, + {self._afk_command_channel_id}, + {self._help_voice_channel_id}, + {self._team_channel_id}, + {self._login_message_channel_id}, + {self._server.id} + ); + """ + ) + + @property + def udpate_string(self) -> str: + return str( + f""" + UPDATE `CFG_Server` + SET `MessageDeleteTimer` = {self._message_delete_timer}, + `NotificationChatId` = {self._notification_chat_id}, + `MaxVoiceStateHours` = {self._max_voice_state_hours}, + `XpPerMessage` = {self._xp_per_message}, + `XpPerReaction` = {self._xp_per_reaction}, + `MaxMessageXpPerHour` = {self._max_message_xp_per_hour}, + `XpPerOntimeHour` = {self._xp_per_ontime_hour}, + `XpPerEventParticipation` = {self._xp_per_event_participation}, + `XpPerAchievement` = {self._xp_per_achievement}, + `AFKCommandChannelId` = {self._afk_command_channel_id}, + `HelpVoiceChannelId` = {self._help_voice_channel_id}, + `TeamChannelId` = {self._team_channel_id}, + `LoginMessageChannelId` = {self._login_message_channel_id}, + `ServerId` = {self._server.id} + WHERE `Id` = {self._id}; + """ + ) + + @property + def delete_string(self) -> str: + return str( + f""" + DELETE FROM `CFG_Server` + WHERE `Id` = {self._id}; + """ + ) diff --git a/kdb-bot/src/bot_data/model/server_config_history.py b/kdb-bot/src/bot_data/model/server_config_history.py new file mode 100644 index 00000000..d96e8473 --- /dev/null +++ b/kdb-bot/src/bot_data/model/server_config_history.py @@ -0,0 +1,102 @@ +from bot_data.abc.history_table_abc import HistoryTableABC + + +class ServerConfigHistory(HistoryTableABC): + def __init__( + self, + message_delete_timer: int, + notification_chat_id: int, + max_voice_state_hours: int, + xp_per_message: int, + xp_per_reaction: int, + max_message_xp_per_hour: int, + xp_per_ontime_hour: int, + xp_per_event_participation: int, + xp_per_achievement: int, + afk_command_channel_id: int, + help_voice_channel_id: int, + team_channel_id: int, + login_message_channel_id: int, + server_id: int, + deleted: bool, + date_from: str, + date_to: str, + id=0, + ): + HistoryTableABC.__init__(self) + + self._id = id + self._message_delete_timer = message_delete_timer + self._notification_chat_id = notification_chat_id + self._max_voice_state_hours = max_voice_state_hours + self._xp_per_message = xp_per_message + self._xp_per_reaction = xp_per_reaction + self._max_message_xp_per_hour = max_message_xp_per_hour + self._xp_per_ontime_hour = xp_per_ontime_hour + self._xp_per_event_participation = xp_per_event_participation + self._xp_per_achievement = xp_per_achievement + self._afk_command_channel_id = afk_command_channel_id + self._help_voice_channel_id = help_voice_channel_id + self._team_channel_id = team_channel_id + self._login_message_channel_id = login_message_channel_id + self._server_id = server_id + + self._deleted = deleted + self._date_from = date_from + self._date_to = date_to + + @property + def message_delete_timer(self) -> int: + return self._message_delete_timer + + @property + def notification_chat_id(self) -> int: + return self._notification_chat_id + + @property + def max_voice_state_hours(self) -> int: + return self._max_voice_state_hours + + @property + def xp_per_message(self) -> int: + return self._xp_per_message + + @property + def xp_per_reaction(self) -> int: + return self._xp_per_reaction + + @property + def max_message_xp_per_hour(self) -> int: + return self._max_message_xp_per_hour + + @property + def xp_per_ontime_hour(self) -> int: + return self._xp_per_ontime_hour + + @property + def xp_per_event_participation(self) -> int: + return self._xp_per_event_participation + + @property + def xp_per_achievement(self) -> int: + return self._xp_per_achievement + + @property + def afk_command_channel_id(self) -> int: + return self._afk_command_channel_id + + @property + def help_voice_channel_id(self) -> int: + return self._help_voice_channel_id + + @property + def team_channel_id(self) -> int: + return self._team_channel_id + + @property + def login_message_channel_id(self) -> int: + return self._login_message_channel_id + + @property + def server_id(self) -> int: + return self._server_id diff --git a/kdb-bot/src/bot_data/model/server_team_role_ids_config.py b/kdb-bot/src/bot_data/model/server_team_role_ids_config.py new file mode 100644 index 00000000..dfd870dd --- /dev/null +++ b/kdb-bot/src/bot_data/model/server_team_role_ids_config.py @@ -0,0 +1,100 @@ +from datetime import datetime + +from cpl_core.database import TableABC + +from bot_data.model.team_member_type_enum import TeamMemberTypeEnum + + +class ServerTeamRoleIdsConfig(TableABC): + def __init__( + self, + role_id: int, + team_member_type: TeamMemberTypeEnum, + server_id: int, + created_at: datetime = None, + modified_at: datetime = None, + id=0, + ): + self._id = id + self._role_id = role_id + self._team_member_type = team_member_type + self._server_id = server_id + + TableABC.__init__(self) + self._created_at = created_at if created_at is not None else self._created_at + self._modified_at = modified_at if modified_at is not None else self._modified_at + + @property + def id(self) -> int: + return self._id + + @property + def role_id(self) -> int: + return self._role_id + + @property + def team_member_type(self) -> TeamMemberTypeEnum: + return self._team_member_type + + @staticmethod + def get_select_all_string() -> str: + return str( + f""" + SELECT * FROM `CFG_ServerTeamRoleIds`; + """ + ) + + @staticmethod + def get_select_by_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `CFG_ServerTeamRoleIds` + WHERE `Id` = {id}; + """ + ) + + @staticmethod + def get_select_by_server_id_string(server_id: int) -> str: + return str( + f""" + SELECT * FROM `CFG_ServerTeamRoleIds` + WHERE `ServerId` = {server_id}; + """ + ) + + @property + def insert_string(self) -> str: + return str( + f""" + INSERT INTO `CFG_ServerTeamRoleIds` ( + `RoleId`, + `TeamMemberType`, + `ServerId` + ) VALUES ( + {self._role_id}, + '{self._team_member_type.value}', + {self._server_id} + ); + """ + ) + + @property + def udpate_string(self) -> str: + return str( + f""" + UPDATE `CFG_ServerTeamRoleIds` + SET `RoleId` = {self._role_id}, + `TeamMemberType` = '{self._team_member_type.value}', + `ServerId` = {self._server_id} + WHERE `Id` = {self._id}; + """ + ) + + @property + def delete_string(self) -> str: + return str( + f""" + DELETE FROM `CFG_ServerTeamRoleIds` + WHERE `RoleId` = {self._role_id}; + """ + ) diff --git a/kdb-bot/src/bot_data/model/team_member_type_enum.py b/kdb-bot/src/bot_data/model/team_member_type_enum.py new file mode 100644 index 00000000..86b3b41d --- /dev/null +++ b/kdb-bot/src/bot_data/model/team_member_type_enum.py @@ -0,0 +1,6 @@ +from enum import Enum + + +class TeamMemberTypeEnum(Enum): + moderator = "Moderator" + admin = "Admin" diff --git a/kdb-bot/src/bot_data/model/technician_config.py b/kdb-bot/src/bot_data/model/technician_config.py new file mode 100644 index 00000000..db43a82c --- /dev/null +++ b/kdb-bot/src/bot_data/model/technician_config.py @@ -0,0 +1,137 @@ +from datetime import datetime + +from cpl_core.configuration import ConfigurationModelABC +from cpl_core.database import TableABC +from cpl_query.extension import List + + +class TechnicianConfig(TableABC, ConfigurationModelABC): + def __init__( + self, + help_command_reference_url: str, + wait_for_restart: int, + wait_for_shutdown: int, + cache_max_messages: int, + technician_ids: List[int], + ping_urls: List[str], + created_at: datetime = None, + modified_at: datetime = None, + id=0, + ): + self._id = id + self._help_command_reference_url = help_command_reference_url + self._wait_for_restart = wait_for_restart + self._wait_for_shutdown = wait_for_shutdown + self._cache_max_messages = cache_max_messages + self._technician_ids = technician_ids + self._ping_urls = ping_urls + + TableABC.__init__(self) + self._created_at = created_at if created_at is not None else self._created_at + self._modified_at = modified_at if modified_at is not None else self._modified_at + + @property + def id(self) -> int: + return self._id + + @property + def help_command_reference_url(self) -> str: + return self._help_command_reference_url + + @help_command_reference_url.setter + def help_command_reference_url(self, value: str): + self._help_command_reference_url = value + + @property + def wait_for_restart(self) -> int: + return self._wait_for_restart + + @wait_for_restart.setter + def wait_for_restart(self, value: int): + self._wait_for_restart = value + + @property + def wait_for_shutdown(self) -> int: + return self._wait_for_shutdown + + @wait_for_shutdown.setter + def wait_for_shutdown(self, value: int): + self._wait_for_shutdown = value + + @property + def cache_max_messages(self) -> int: + return self._cache_max_messages + + @cache_max_messages.setter + def cache_max_messages(self, value: int): + self._cache_max_messages = value + + @property + def technician_ids(self) -> List[int]: + return self._technician_ids + + @technician_ids.setter + def technician_ids(self, value: List[int]): + self._technician_ids = value + + @property + def ping_urls(self) -> List[str]: + return self._ping_urls + + @ping_urls.setter + def ping_urls(self, value: List[str]): + self._ping_urls = value + + @staticmethod + def get_select_all_string() -> str: + return str( + f""" + SELECT * FROM `CFG_Technician`; + """ + ) + + @staticmethod + def get_select_by_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `CFG_Technician` + WHERE `Id` = {id}; + """ + ) + + @property + def insert_string(self) -> str: + return str( + f""" + INSERT INTO `CFG_Technician` ( + `HelpCommandReferenceUrl`, `WaitForRestart`, `WaitForShutdown`, `CacheMaxMessages` + ) VALUES ( + '{self._help_command_reference_url}', + {self._wait_for_restart}, + {self._wait_for_shutdown}, + {self._cache_max_messages} + ); + """ + ) + + @property + def udpate_string(self) -> str: + return str( + f""" + UPDATE `CFG_Technician` + SET `HelpCommandReferenceUrl` = '{self._help_command_reference_url}', + `WaitForRestart` = {self._wait_for_restart}, + `WaitForShutdown` = {self._wait_for_shutdown}, + `CacheMaxMessages` = {self._cache_max_messages} + WHERE `Id` = {self._id}; + """ + ) + + @property + def delete_string(self) -> str: + return str( + f""" + DELETE FROM `CFG_Technician` + WHERE `Id` = {self._id}; + """ + ) diff --git a/kdb-bot/src/bot_data/model/technician_config_history.py b/kdb-bot/src/bot_data/model/technician_config_history.py new file mode 100644 index 00000000..7575607f --- /dev/null +++ b/kdb-bot/src/bot_data/model/technician_config_history.py @@ -0,0 +1,58 @@ +from bot_data.abc.history_table_abc import HistoryTableABC + + +class TechnicianConfigHistory(HistoryTableABC): + def __init__( + self, + help_command_reference_url: str, + wait_for_restart: int, + wait_for_shutdown: int, + cache_max_messages: int, + deleted: bool, + date_from: str, + date_to: str, + id=0, + ): + HistoryTableABC.__init__(self) + + self._id = id + self._help_command_reference_url = help_command_reference_url + self._wait_for_restart = wait_for_restart + self._wait_for_shutdown = wait_for_shutdown + self._cache_max_messages = cache_max_messages + + self._deleted = deleted + self._date_from = date_from + self._date_to = date_to + + @property + def help_command_reference_url(self) -> str: + return self._help_command_reference_url + + @help_command_reference_url.setter + def help_command_reference_url(self, value: str): + self._help_command_reference_url = value + + @property + def wait_for_restart(self) -> int: + return self._wait_for_restart + + @wait_for_restart.setter + def wait_for_restart(self, value: int): + self._wait_for_restart = value + + @property + def wait_for_shutdown(self) -> int: + return self._wait_for_shutdown + + @wait_for_shutdown.setter + def wait_for_shutdown(self, value: int): + self._wait_for_shutdown = value + + @property + def cache_max_messages(self) -> int: + return self._cache_max_messages + + @cache_max_messages.setter + def cache_max_messages(self, value: int): + self._cache_max_messages = value diff --git a/kdb-bot/src/bot_data/model/technician_id_config.py b/kdb-bot/src/bot_data/model/technician_id_config.py new file mode 100644 index 00000000..6ba5f581 --- /dev/null +++ b/kdb-bot/src/bot_data/model/technician_id_config.py @@ -0,0 +1,79 @@ +from datetime import datetime + +from cpl_core.database import TableABC + + +class TechnicianIdConfig(TableABC): + def __init__( + self, + technician_id: str, + created_at: datetime = None, + modified_at: datetime = None, + id=0, + ): + self._id = id + self._technician_id = technician_id + + TableABC.__init__(self) + self._created_at = created_at if created_at is not None else self._created_at + self._modified_at = modified_at if modified_at is not None else self._modified_at + + @property + def id(self) -> int: + return self._id + + @property + def technician_id(self) -> str: + return self._technician_id + + @technician_id.setter + def technician_id(self, value: str): + self._technician_id = value + + @staticmethod + def get_select_all_string() -> str: + return str( + f""" + SELECT * FROM `CFG_TechnicianIds`; + """ + ) + + @staticmethod + def get_select_by_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `CFG_TechnicianIds` + WHERE `Id` = {id}; + """ + ) + + @property + def insert_string(self) -> str: + return str( + f""" + INSERT INTO `CFG_TechnicianIds` ( + `TechnicianId` + ) VALUES ( + '{self._technician_id}' + ); + """ + ) + + @property + def udpate_string(self) -> str: + return str( + f""" + UPDATE `CFG_TechnicianIds` + SET `TechnicianId` = '{self._technician_id}' + WHERE `Id` = {self._id}; + """ + ) + + @property + def delete_string(self) -> str: + return str( + f""" + DELETE FROM `CFG_TechnicianIds` + WHERE `TechnicianId` = {self._technician_id}; + """ + ) diff --git a/kdb-bot/src/bot_data/model/technician_id_config_history.py b/kdb-bot/src/bot_data/model/technician_id_config_history.py new file mode 100644 index 00000000..dbb6a1f9 --- /dev/null +++ b/kdb-bot/src/bot_data/model/technician_id_config_history.py @@ -0,0 +1,28 @@ +from bot_data.abc.history_table_abc import HistoryTableABC + + +class TechnicianIdConfigHistory(HistoryTableABC): + def __init__( + self, + technician_id: int, + deleted: bool, + date_from: str, + date_to: str, + id=0, + ): + HistoryTableABC.__init__(self) + + self._id = id + self._technician_id = technician_id + + self._deleted = deleted + self._date_from = date_from + self._date_to = date_to + + @property + def technician_id(self) -> int: + return self._technician_id + + @technician_id.setter + def technician_id(self, value: int): + self._technician_id = value diff --git a/kdb-bot/src/bot_data/model/technician_ping_url_config.py b/kdb-bot/src/bot_data/model/technician_ping_url_config.py new file mode 100644 index 00000000..31983624 --- /dev/null +++ b/kdb-bot/src/bot_data/model/technician_ping_url_config.py @@ -0,0 +1,79 @@ +from datetime import datetime + +from cpl_core.database import TableABC + + +class TechnicianPingUrlConfig(TableABC): + def __init__( + self, + ping_url: str, + created_at: datetime = None, + modified_at: datetime = None, + id=0, + ): + self._id = id + self._ping_url = ping_url + + TableABC.__init__(self) + self._created_at = created_at if created_at is not None else self._created_at + self._modified_at = modified_at if modified_at is not None else self._modified_at + + @property + def id(self) -> int: + return self._id + + @property + def ping_url(self) -> str: + return self._ping_url + + @ping_url.setter + def ping_url(self, value: str): + self._ping_url = value + + @staticmethod + def get_select_all_string() -> str: + return str( + f""" + SELECT * FROM `CFG_TechnicianPingUrls`; + """ + ) + + @staticmethod + def get_select_by_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `CFG_TechnicianPingUrls` + WHERE `Id` = {id}; + """ + ) + + @property + def insert_string(self) -> str: + return str( + f""" + INSERT INTO `CFG_TechnicianPingUrls` ( + `URL` + ) VALUES ( + '{self._ping_url}' + ); + """ + ) + + @property + def udpate_string(self) -> str: + return str( + f""" + UPDATE `CFG_TechnicianPingUrls` + SET `URL` = '{self._ping_url}' + WHERE `Id` = {self._id}; + """ + ) + + @property + def delete_string(self) -> str: + return str( + f""" + DELETE FROM `CFG_TechnicianPingUrls` + WHERE `URL` = '{self._ping_url}'; + """ + ) diff --git a/kdb-bot/src/bot_data/model/technician_ping_url_config_history.py b/kdb-bot/src/bot_data/model/technician_ping_url_config_history.py new file mode 100644 index 00000000..9483f981 --- /dev/null +++ b/kdb-bot/src/bot_data/model/technician_ping_url_config_history.py @@ -0,0 +1,28 @@ +from bot_data.abc.history_table_abc import HistoryTableABC + + +class TechnicianPingUrlConfigHistory(HistoryTableABC): + def __init__( + self, + url: str, + deleted: bool, + date_from: str, + date_to: str, + id=0, + ): + HistoryTableABC.__init__(self) + + self._id = id + self._url = url + + self._deleted = deleted + self._date_from = date_from + self._date_to = date_to + + @property + def url(self) -> str: + return self._url + + @url.setter + def url(self, value: str): + self._url = value diff --git a/kdb-bot/src/bot_data/service/server_config_repository_service.py b/kdb-bot/src/bot_data/service/server_config_repository_service.py new file mode 100644 index 00000000..09c1bff5 --- /dev/null +++ b/kdb-bot/src/bot_data/service/server_config_repository_service.py @@ -0,0 +1,125 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_query.extension import List + +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.server_config_repository_abc import ServerConfigRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.model.server_afk_channel_ids_config import ServerAFKChannelIdsConfig +from bot_data.model.server_config import ServerConfig +from bot_data.model.server_team_role_ids_config import ServerTeamRoleIdsConfig +from bot_data.model.team_member_type_enum import TeamMemberTypeEnum + + +class ServerConfigRepositoryService(ServerConfigRepositoryABC): + def __init__(self, logger: DatabaseLogger, db_context: DatabaseContextABC, servers: ServerRepositoryABC): + ServerConfigRepositoryABC.__init__(self) + + self._logger = logger + self._context = db_context + self._servers = servers + + def _get_team_role_ids(self, server_id: int) -> List[ServerTeamRoleIdsConfig]: + ids = List(ServerTeamRoleIdsConfig) + self._logger.trace( + __name__, f"Send SQL command: {ServerTeamRoleIdsConfig.get_select_by_server_id_string(server_id)}" + ) + results = self._context.select(ServerTeamRoleIdsConfig.get_select_by_server_id_string(server_id)) + for result in results: + self._logger.trace(__name__, f"Got ServerTeamRoleIdsConfig with id {result[0]}") + ids.append( + ServerTeamRoleIdsConfig( + result[1], TeamMemberTypeEnum(result[2]), result[3], result[4], result[5], id=result[0] + ) + ) + + return ids + + def _get_afk_channel_ids(self, server_id: int) -> List[int]: + urls = List(int) + self._logger.trace( + __name__, + f"Send SQL command: {ServerAFKChannelIdsConfig.get_select_by_server_id_string(server_id)}", + ) + results = self._context.select(ServerAFKChannelIdsConfig.get_select_by_server_id_string(server_id)) + for result in results: + self._logger.trace(__name__, f"Got ServerAFKChannelIdsConfig with id {result[0]}") + urls.append(result[1]) + + return urls + + def _from_result(self, result: tuple) -> ServerConfig: + return ServerConfig( + result[1], + result[2], + result[3], + result[4], + result[5], + result[6], + result[7], + result[8], + result[9], + result[10], + result[11], + result[12], + result[13], + self._servers.get_server_by_id(result[14]), + self._get_afk_channel_ids(result[14]), + self._get_team_role_ids(result[14]), + result[15], + result[16], + id=result[0], + ) + + def does_server_config_exists(self, server_id: int) -> bool: + self._logger.trace(__name__, f"Send SQL command: {ServerConfig.get_select_by_id_string(server_id)}") + result = self._context.select(ServerConfig.get_select_by_id_string(server_id)) + + return len(result) > 0 + + def get_server_config_by_server(self, server_id: int) -> ServerConfig: + self._logger.trace(__name__, f"Send SQL command: {ServerConfig.get_select_by_id_string(server_id)}") + result = self._context.select(ServerConfig.get_select_by_id_string(server_id))[0] + + return self._from_result(result) + + def get_server_config_by_id(self, config_id: int) -> ServerConfig: + self._logger.trace(__name__, f"Send SQL command: {ServerConfig.get_select_by_id_string(config_id)}") + result = self._context.select(ServerConfig.get_select_by_id_string(config_id))[0] + + return self._from_result(result) + + def add_server_config(self, server_config: ServerConfig): + self._logger.trace(__name__, f"Send SQL command: {server_config.insert_string}") + self._context.cursor.execute(server_config.insert_string) + + def update_server_config(self, server_config: ServerConfig): + self._logger.trace(__name__, f"Send SQL command: {server_config.udpate_string}") + self._context.cursor.execute(server_config.udpate_string) + + def delete_server_config(self, server_config: ServerConfig): + self._logger.trace(__name__, f"Send SQL command: {server_config.delete_string}") + self._context.cursor.execute(server_config.delete_string) + + def add_server_team_role_id_config(self, server_team_role_id: ServerTeamRoleIdsConfig): + self._logger.trace(__name__, f"Send SQL command: {server_team_role_id.insert_string}") + self._context.cursor.execute(server_team_role_id.insert_string) + + def update_server_team_role_id_config(self, server_team_role_id: ServerTeamRoleIdsConfig): + self._logger.trace(__name__, f"Send SQL command: {server_team_role_id.udpate_string}") + self._context.cursor.execute(server_team_role_id.udpate_string) + + def delete_server_team_role_id_config(self, server_team_role_id: ServerTeamRoleIdsConfig): + self._logger.trace(__name__, f"Send SQL command: {server_team_role_id.delete_string}") + self._context.cursor.execute(server_team_role_id.delete_string) + + def add_server_afk_channel_config(self, server_afk_channel: ServerAFKChannelIdsConfig): + self._logger.trace(__name__, f"Send SQL command: {server_afk_channel.insert_string}") + self._context.cursor.execute(server_afk_channel.insert_string) + + def update_server_afk_channel_config(self, server_afk_channel: ServerAFKChannelIdsConfig): + self._logger.trace(__name__, f"Send SQL command: {server_afk_channel.udpate_string}") + self._context.cursor.execute(server_afk_channel.udpate_string) + + def delete_server_afk_channel_config(self, server_afk_channel: ServerAFKChannelIdsConfig): + self._logger.trace(__name__, f"Send SQL command: {server_afk_channel.delete_string}") + self._context.cursor.execute(server_afk_channel.delete_string) diff --git a/kdb-bot/src/bot_data/service/server_config_seeder.py b/kdb-bot/src/bot_data/service/server_config_seeder.py new file mode 100644 index 00000000..c80f3997 --- /dev/null +++ b/kdb-bot/src/bot_data/service/server_config_seeder.py @@ -0,0 +1,62 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.container import Guild +from cpl_discord.service import DiscordBotServiceABC + +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.data_seeder_abc import DataSeederABC +from bot_data.abc.server_config_repository_abc import ServerConfigRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.model.server_config import ServerConfig + + +class ServerConfigSeeder(DataSeederABC): + def __init__( + self, + logger: DatabaseLogger, + bot: DiscordBotServiceABC, + servers: ServerRepositoryABC, + server_config: ServerConfigRepositoryABC, + db: DatabaseContextABC, + ): + DataSeederABC.__init__(self) + + self._logger = logger + self._bot = bot + self._servers = servers + self._server_config = server_config + self._db = db + + async def seed(self): + try: + for guild in self._bot.guilds: + guild: Guild = guild + server = self._servers.get_server_by_discord_id(guild.id) + if self._server_config.does_server_config_exists(server.id): + continue + + config = ServerConfig( + 6, + guild.system_channel.id, + 6, + 1, + 1, + 20, + 10, + 10, + 10, + guild.system_channel.id, + guild.system_channel.id, + guild.system_channel.id, + guild.system_channel.id, + server, + [], + [], + ) + + self._server_config.add_server_config(config) + + self._db.save_changes() + self._logger.debug(__name__, "Seeded technician config") + + except Exception as e: + self._logger.error(__name__, f"Seeding technician config failed", e) diff --git a/kdb-bot/src/bot_data/service/technician_config_repository_service.py b/kdb-bot/src/bot_data/service/technician_config_repository_service.py new file mode 100644 index 00000000..3e1354cb --- /dev/null +++ b/kdb-bot/src/bot_data/service/technician_config_repository_service.py @@ -0,0 +1,97 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_query.extension import List + +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.technician_config_repository_abc import TechnicianConfigRepositoryABC +from bot_data.model.technician_config import TechnicianConfig +from bot_data.model.technician_id_config import TechnicianIdConfig +from bot_data.model.technician_ping_url_config import TechnicianPingUrlConfig + + +class TechnicianConfigRepositoryService(TechnicianConfigRepositoryABC): + def __init__(self, logger: DatabaseLogger, db_context: DatabaseContextABC): + TechnicianConfigRepositoryABC.__init__(self) + + self._logger = logger + self._context = db_context + + def _get_technician_ids(self) -> List[int]: + ids = List(int) + self._logger.trace(__name__, f"Send SQL command: {TechnicianIdConfig.get_select_all_string()}") + results = self._context.select(TechnicianIdConfig.get_select_all_string()) + for result in results: + self._logger.trace(__name__, f"Got TechnicianId with id {result[0]}") + ids.append(result[1]) + + return ids + + def _get_technician_ping_urls(self) -> List[str]: + urls = List(str) + self._logger.trace(__name__, f"Send SQL command: {TechnicianPingUrlConfig.get_select_all_string()}") + results = self._context.select(TechnicianPingUrlConfig.get_select_all_string()) + for result in results: + self._logger.trace(__name__, f"Got TechnicianPingUrl with id {result[0]}") + urls.append(result[1]) + + return urls + + def _from_result(self, result: tuple) -> TechnicianConfig: + return TechnicianConfig( + result[1], + result[2], + result[3], + result[4], + self._get_technician_ids(), + self._get_technician_ping_urls(), + result[5], + result[6], + id=result[0], + ) + + def does_technician_config_exists(self) -> bool: + self._logger.trace(__name__, f"Send SQL command: {TechnicianConfig.get_select_all_string()}") + result = self._context.select(TechnicianConfig.get_select_all_string()) + + return len(result) > 0 + + def get_technician_config(self) -> TechnicianConfig: + self._logger.trace(__name__, f"Send SQL command: {TechnicianConfig.get_select_all_string()}") + result = self._context.select(TechnicianConfig.get_select_all_string())[0] + + return self._from_result(result) + + def add_technician_config(self, technician_config: TechnicianConfig): + self._logger.trace(__name__, f"Send SQL command: {technician_config.insert_string}") + self._context.cursor.execute(technician_config.insert_string) + + def update_technician_config(self, technician_config: TechnicianConfig): + self._logger.trace(__name__, f"Send SQL command: {technician_config.udpate_string}") + self._context.cursor.execute(technician_config.udpate_string) + + def delete_technician_config(self, technician_config: TechnicianConfig): + self._logger.trace(__name__, f"Send SQL command: {technician_config.delete_string}") + self._context.cursor.execute(technician_config.delete_string) + + def add_technician_id_config(self, technician_id: TechnicianIdConfig): + self._logger.trace(__name__, f"Send SQL command: {technician_id.insert_string}") + self._context.cursor.execute(technician_id.insert_string) + + def update_technician_id_config(self, technician_id: TechnicianIdConfig): + self._logger.trace(__name__, f"Send SQL command: {technician_id.udpate_string}") + self._context.cursor.execute(technician_id.udpate_string) + + def delete_technician_id_config(self, technician_id: TechnicianIdConfig): + self._logger.trace(__name__, f"Send SQL command: {technician_id.delete_string}") + self._context.cursor.execute(technician_id.delete_string) + + def add_technician_ping_url_config(self, technician_ping_url: TechnicianPingUrlConfig): + self._logger.trace(__name__, f"Send SQL command: {technician_ping_url.insert_string}") + self._context.cursor.execute(technician_ping_url.insert_string) + + def update_technician_ping_url_config(self, technician_ping_url: TechnicianPingUrlConfig): + self._logger.trace(__name__, f"Send SQL command: {technician_ping_url.udpate_string}") + self._context.cursor.execute(technician_ping_url.udpate_string) + + def delete_technician_ping_url_config(self, technician_ping_url: TechnicianPingUrlConfig): + self._logger.trace(__name__, f"Send SQL command: {technician_ping_url.delete_string}") + self._context.cursor.execute(technician_ping_url.delete_string) diff --git a/kdb-bot/src/bot_data/service/technician_config_seeder.py b/kdb-bot/src/bot_data/service/technician_config_seeder.py new file mode 100644 index 00000000..ce2be05d --- /dev/null +++ b/kdb-bot/src/bot_data/service/technician_config_seeder.py @@ -0,0 +1,49 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_query.extension import List + +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.data_seeder_abc import DataSeederABC +from bot_data.abc.technician_config_repository_abc import TechnicianConfigRepositoryABC +from bot_data.model.technician_config import TechnicianConfig +from bot_data.model.technician_id_config import TechnicianIdConfig +from bot_data.model.technician_ping_url_config import TechnicianPingUrlConfig + + +class TechnicianConfigSeeder(DataSeederABC): + def __init__( + self, + logger: DatabaseLogger, + technician_config: TechnicianConfigRepositoryABC, + db: DatabaseContextABC, + ): + DataSeederABC.__init__(self) + + self._logger = logger + self._technician_config = technician_config + self._db = db + + async def seed(self): + try: + if self._technician_config.does_technician_config_exists(): + return + + config = TechnicianConfig( + "https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot/wiki/Befehle", + 8, + 8, + 1000000, + List(int, [240160344557879316]), + List(str, ["www.google.com", "www.sh-edraft.de", "www.keksdose-gaming.de"]), + ) + + self._technician_config.add_technician_config(config) + for technician in config.technician_ids: + self._technician_config.add_technician_id_config(TechnicianIdConfig(technician)) + + for url in config.ping_urls: + self._technician_config.add_technician_ping_url_config(TechnicianPingUrlConfig(url)) + + self._db.save_changes() + self._logger.debug(__name__, "Seeded technician config") + except Exception as e: + self._logger.error(__name__, f"Seeding technician config failed", e) diff --git a/kdb-bot/src/bot_graphql/graphql_module.py b/kdb-bot/src/bot_graphql/graphql_module.py index 480b4abc..2b294950 100644 --- a/kdb-bot/src/bot_graphql/graphql_module.py +++ b/kdb-bot/src/bot_graphql/graphql_module.py @@ -24,6 +24,8 @@ from bot_graphql.mutations.achievement_mutation import AchievementMutation from bot_graphql.mutations.auto_role_mutation import AutoRoleMutation from bot_graphql.mutations.auto_role_rule_mutation import AutoRoleRuleMutation from bot_graphql.mutations.level_mutation import LevelMutation +from bot_graphql.mutations.server_config_mutation import ServerConfigMutation +from bot_graphql.mutations.technician_config_mutation import TechnicianConfigMutation from bot_graphql.mutations.user_joined_game_server_mutation import UserJoinedGameServerMutation from bot_graphql.mutations.user_mutation import UserMutation from bot_graphql.queries.achievement_attribute_query import AchievementAttributeQuery @@ -40,8 +42,13 @@ from bot_graphql.queries.known_user_history_query import KnownUserHistoryQuery from bot_graphql.queries.known_user_query import KnownUserQuery from bot_graphql.queries.level_history_query import LevelHistoryQuery from bot_graphql.queries.level_query import LevelQuery +from bot_graphql.queries.server_config_query import ServerConfigQuery from bot_graphql.queries.server_history_query import ServerHistoryQuery from bot_graphql.queries.server_query import ServerQuery +from bot_graphql.queries.technician_config_history_query import TechnicianConfigHistoryQuery +from bot_graphql.queries.technician_config_query import TechnicianConfigQuery +from bot_graphql.queries.technician_id_config_history_query import TechnicianIdConfigHistoryQuery +from bot_graphql.queries.technician_ping_url_config_history_query import TechnicianPingUrlConfigHistoryQuery from bot_graphql.queries.user_history_query import UserHistoryQuery from bot_graphql.queries.user_joined_game_server_history_query import UserJoinedGameServerHistoryQuery from bot_graphql.queries.user_joined_game_server_query import UserJoinedGameServerQuery @@ -81,8 +88,13 @@ class GraphQLModule(ModuleABC): services.add_transient(QueryABC, KnownUserQuery) services.add_transient(QueryABC, LevelHistoryQuery) services.add_transient(QueryABC, LevelQuery) + services.add_transient(QueryABC, ServerConfigQuery) services.add_transient(QueryABC, ServerHistoryQuery) services.add_transient(QueryABC, ServerQuery) + services.add_transient(QueryABC, TechnicianConfigQuery) + services.add_transient(QueryABC, TechnicianConfigHistoryQuery) + services.add_transient(QueryABC, TechnicianPingUrlConfigHistoryQuery) + services.add_transient(QueryABC, TechnicianIdConfigHistoryQuery) services.add_transient(QueryABC, GameServerQuery) services.add_transient(QueryABC, UserHistoryQuery) services.add_transient(QueryABC, UserQuery) @@ -112,5 +124,7 @@ class GraphQLModule(ModuleABC): services.add_transient(QueryABC, UserMutation) services.add_transient(QueryABC, AchievementMutation) services.add_transient(QueryABC, UserJoinedGameServerMutation) + services.add_transient(QueryABC, TechnicianConfigMutation) + services.add_transient(QueryABC, ServerConfigMutation) services.add_transient(SeederService) diff --git a/kdb-bot/src/bot_graphql/model/mutation.gql b/kdb-bot/src/bot_graphql/model/mutation.gql index 0fb69b50..aa1d8cd6 100644 --- a/kdb-bot/src/bot_graphql/model/mutation.gql +++ b/kdb-bot/src/bot_graphql/model/mutation.gql @@ -5,4 +5,6 @@ type Mutation { user: UserMutation userJoinedGameServer: UserJoinedGameServerMutation achievement: AchievementMutation + technicianConfig: TechnicianConfigMutation + serverConfig: ServerConfigMutation } \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/query.gql b/kdb-bot/src/bot_graphql/model/query.gql index fefde64d..abb3048a 100644 --- a/kdb-bot/src/bot_graphql/model/query.gql +++ b/kdb-bot/src/bot_graphql/model/query.gql @@ -37,5 +37,7 @@ type Query { achievementAttributes: [AchievementAttribute] achievementOperators: [String] + technicianConfig: TechnicianConfig + guilds(filter: GuildFilter): [Guild] } \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/server.gql b/kdb-bot/src/bot_graphql/model/server.gql index c4689ac9..be754bdb 100644 --- a/kdb-bot/src/bot_graphql/model/server.gql +++ b/kdb-bot/src/bot_graphql/model/server.gql @@ -31,6 +31,8 @@ type Server implements TableWithHistoryQuery { achievementCount: Int achievements(filter: AchievementFilter, page: Page, sort: Sort): [Achievement] + config: ServerConfig + createdAt: String modifiedAt: String diff --git a/kdb-bot/src/bot_graphql/model/serverConfig.gql b/kdb-bot/src/bot_graphql/model/serverConfig.gql new file mode 100644 index 00000000..b16fa139 --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/serverConfig.gql @@ -0,0 +1,94 @@ +type ServerConfig implements TableWithHistoryQuery { + id: ID + messageDeleteTimer: Int + notificationChatId: String + maxVoiceStateHours: Int + xpPerMessage: Int + xpPerReaction: Int + maxMessageXpPerHour: Int + xpPerOntimeHour: Int + xpPerEventParticipation: Int + xpPerAchievement: Int + afkCommandChannelId: String + helpVoiceChannelId: String + teamChannelId: String + loginMessageChannelId: String + + afkChannelIds: [String] + moderatorRoleIds: [String] + adminRoleIds: [String] + + server: Server + + createdAt: String + modifiedAt: String + + history: [ServerConfigHistory] +} + +type ServerConfigHistory implements HistoryTableQuery { + id: ID + messageDeleteTimer: Int + notificationChatId: String + maxVoiceStateHours: Int + xpPerMessage: Int + xpPerReaction: Int + maxMessageXpPerHour: Int + xpPerOntimeHour: Int + xpPerEventParticipation: Int + xpPerAchievement: Int + afkCommandChannelId: String + helpVoiceChannelId: String + teamChannelId: String + loginMessageChannelId: String + + serverId: ID + + deleted: Boolean + dateFrom: String + dateTo: String +} + +type ServerAFKChannelIdsConfigHistory implements HistoryTableQuery { + id: ID + channelId: String + + deleted: Boolean + dateFrom: String + dateTo: String +} + +type ServerTeamRoleIdsConfigHistory implements HistoryTableQuery { + id: ID + roleId: String + teamMemberType: String + + deleted: Boolean + dateFrom: String + dateTo: String +} + +type ServerConfigMutation { + updateServerConfig(input: ServerConfigInput!): ServerConfig +} + +input ServerConfigInput { + id: ID + messageDeleteTimer: Int + notificationChatId: String + maxVoiceStateHours: Int + xpPerMessage: Int + xpPerReaction: Int + maxMessageXpPerHour: Int + xpPerOntimeHour: Int + xpPerEventParticipation: Int + xpPerAchievement: Int + afkCommandChannelId: String + helpVoiceChannelId: String + teamChannelId: String + loginMessageChannelId: String + + afkChannelIds: [String] + moderatorRoleIds: [String] + adminRoleIds: [String] +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/technicianConfig.gql b/kdb-bot/src/bot_graphql/model/technicianConfig.gql new file mode 100644 index 00000000..dc35704a --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/technicianConfig.gql @@ -0,0 +1,60 @@ +type TechnicianConfig implements TableWithHistoryQuery { + id: ID + helpCommandReferenceUrl: String + waitForRestart: Int + waitForShutdown: Int + cacheMaxMessages: Int + pingURLs: [String] + technicianIds: [String] + + createdAt: String + modifiedAt: String + + history: [TechnicianConfigHistory] + pingURLHistory: [TechnicianPingUrlConfigHistory] + technicianIdHistory: [TechnicianIdConfigHistory] +} + +type TechnicianConfigHistory implements HistoryTableQuery { + id: ID + helpCommandReferenceUrl: String + waitForRestart: Int + waitForShutdown: Int + cacheMaxMessages: Int + + deleted: Boolean + dateFrom: String + dateTo: String +} + +type TechnicianPingUrlConfigHistory implements HistoryTableQuery { + id: ID + url: String + + deleted: Boolean + dateFrom: String + dateTo: String +} + +type TechnicianIdConfigHistory implements HistoryTableQuery { + id: ID + technicianId: String + + deleted: Boolean + dateFrom: String + dateTo: String +} + +type TechnicianConfigMutation { + updateTechnicianConfig(input: TechnicianConfigInput!): TechnicianConfig +} + +input TechnicianConfigInput { + id: ID + helpCommandReferenceUrl: String + waitForRestart: Int + waitForShutdown: Int + cacheMaxMessages: Int + pingURLs: [String] + technicianIds: [String] +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/mutation.py b/kdb-bot/src/bot_graphql/mutation.py index d8287d96..4631e321 100644 --- a/kdb-bot/src/bot_graphql/mutation.py +++ b/kdb-bot/src/bot_graphql/mutation.py @@ -4,6 +4,8 @@ from bot_graphql.mutations.achievement_mutation import AchievementMutation from bot_graphql.mutations.auto_role_mutation import AutoRoleMutation from bot_graphql.mutations.auto_role_rule_mutation import AutoRoleRuleMutation from bot_graphql.mutations.level_mutation import LevelMutation +from bot_graphql.mutations.server_config_mutation import ServerConfigMutation +from bot_graphql.mutations.technician_config_mutation import TechnicianConfigMutation from bot_graphql.mutations.user_joined_game_server_mutation import UserJoinedGameServerMutation from bot_graphql.mutations.user_mutation import UserMutation @@ -17,6 +19,8 @@ class Mutation(MutationType): user_mutation: UserMutation, achievement_mutation: AchievementMutation, user_joined_game_server: UserJoinedGameServerMutation, + technician_config: TechnicianConfigMutation, + server_config: ServerConfigMutation, ): MutationType.__init__(self) @@ -26,3 +30,5 @@ class Mutation(MutationType): self.set_field("user", lambda *_: user_mutation) self.set_field("achievement", lambda *_: achievement_mutation) self.set_field("userJoinedGameServer", lambda *_: user_joined_game_server) + self.set_field("technicianConfig", lambda *_: technician_config) + self.set_field("serverConfig", lambda *_: server_config) diff --git a/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py b/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py new file mode 100644 index 00000000..2480be82 --- /dev/null +++ b/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py @@ -0,0 +1,163 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_query.extension import List + +from bot_api.logging.api_logger import ApiLogger +from bot_data.abc.server_config_repository_abc import ServerConfigRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.model.server_afk_channel_ids_config import ServerAFKChannelIdsConfig +from bot_data.model.server_config import ServerConfig +from bot_data.model.server_team_role_ids_config import ServerTeamRoleIdsConfig +from bot_data.model.team_member_type_enum import TeamMemberTypeEnum +from bot_data.model.user_role_enum import UserRoleEnum +from bot_graphql.abc.query_abc import QueryABC + + +class ServerConfigMutation(QueryABC): + def __init__( + self, + logger: ApiLogger, + bot: DiscordBotServiceABC, + servers: ServerRepositoryABC, + server_configs: ServerConfigRepositoryABC, + db: DatabaseContextABC, + ): + QueryABC.__init__(self, "ServerConfigMutation") + + self._logger = logger + self._bot = bot + self._servers = servers + self._server_configs = server_configs + self._db = db + + self.set_field("updateServerConfig", self.resolve_update_server_config) + + def resolve_update_server_config(self, *_, input: dict): + if "id" not in input: + raise ValueError("Id not set") + + server_config = self._server_configs.get_server_config_by_server(input["id"]) + self._can_user_mutate_data(server_config, UserRoleEnum.admin) + + server_config.message_delete_timer = ( + input["messageDeleteTimer"] if "messageDeleteTimer" in input else server_config.message_delete_timer + ) + server_config.notification_chat_id = ( + input["notificationChatId"] if "notificationChatId" in input else server_config.notification_chat_id + ) + server_config.max_voice_state_hours = ( + input["maxVoiceStateHours"] if "maxVoiceStateHours" in input else server_config.max_voice_state_hours + ) + server_config.xp_per_message = ( + input["xpPerMessage"] if "xpPerMessage" in input else server_config.xp_per_message + ) + server_config.xp_per_reaction = ( + input["xpPerReaction"] if "xpPerReaction" in input else server_config.xp_per_reaction + ) + server_config.max_message_xp_per_hour = ( + input["maxMessageXpPerHour"] if "maxMessageXpPerHour" in input else server_config.max_message_xp_per_hour + ) + server_config.xp_per_ontime_hour = ( + input["xpPerOntimeHour"] if "xpPerOntimeHour" in input else server_config.xp_per_ontime_hour + ) + server_config.xp_per_event_participation = ( + input["xpPerEventParticipation"] + if "xpPerEventParticipation" in input + else server_config.xp_per_event_participation + ) + server_config.xp_per_achievement = ( + input["xpPerAchievement"] if "xpPerAchievement" in input else server_config.xp_per_achievement + ) + server_config.afk_command_channel_id = ( + input["afkCommandChannelId"] if "afkCommandChannelId" in input else server_config.afk_command_channel_id + ) + server_config.help_voice_channel_id = ( + input["helpVoiceChannelId"] if "helpVoiceChannelId" in input else server_config.help_voice_channel_id + ) + server_config.team_channel_id = ( + input["teamChannelId"] if "teamChannelId" in input else server_config.team_channel_id + ) + server_config.login_message_channel_id = ( + input["loginMessageChannelId"] + if "loginMessageChannelId" in input + else server_config.login_message_channel_id + ) + server_config.afk_channel_ids = ( + List(int).extend([int(x) for x in input["afkChannelIds"]]) + if "afkChannelIds" in input + else server_config.afk_channel_ids + ) + + team_role_ids = List(ServerTeamRoleIdsConfig) + if "moderatorRoleIds" in input: + team_role_ids.extend( + [ + ServerTeamRoleIdsConfig(x, TeamMemberTypeEnum.moderator, server_config.server.id) + for x in input["moderatorRoleIds"] + ] + ) + else: + team_role_ids.extend( + server_config.team_role_ids.where(lambda x: x.team_member_type == TeamMemberTypeEnum.moderator) + ) + + if "adminRoleIds" in input: + team_role_ids.extend( + [ + ServerTeamRoleIdsConfig(x, TeamMemberTypeEnum.admin, server_config.server.id) + for x in input["adminRoleIds"] + ] + ) + else: + team_role_ids.extend( + server_config.team_role_ids.where(lambda x: x.team_member_type == TeamMemberTypeEnum.admin) + ) + + self._server_configs.update_server_config(server_config) + if "afkChannelIds" in input: + self._update_afk_channel_ids(server_config) + + if "moderatorRoleIds" in input or "adminRoleIds" in input: + server_config.team_role_ids = team_role_ids + self._update_team_role_ids(server_config) + + self._db.save_changes() + return server_config + + def _update_afk_channel_ids(self, new_config: ServerConfig): + old_config = self._server_configs.get_server_config_by_id(new_config.server.id) + for channel_id in old_config.afk_channel_ids: + if channel_id in new_config.afk_channel_ids: + continue + + self._server_configs.delete_server_afk_channel_config( + ServerAFKChannelIdsConfig(channel_id, new_config.server.id) + ) + + for channel_id in new_config.afk_channel_ids: + if channel_id in old_config.afk_channel_ids: + continue + + self._server_configs.add_server_afk_channel_config( + ServerAFKChannelIdsConfig(channel_id, new_config.server.id) + ) + + def _update_team_role_ids(self, new_config: ServerConfig): + old_config = self._server_configs.get_server_config_by_id(new_config.server.id) + for role_id in old_config.team_role_ids: + if role_id.role_id in new_config.team_role_ids.select(lambda x: int(x.role_id)): + continue + + self._server_configs.delete_server_team_role_id_config(role_id) + + for role_id in new_config.team_role_ids: + guild = self._bot.get_guild(new_config.server.discord_id) + role = guild.get_role(int(role_id.role_id)) + if role is None: + raise ValueError(f"Invalid roleId") + + for role_id in new_config.team_role_ids: + if role_id.role_id in old_config.team_role_ids.select(lambda x: str(x.role_id)): + continue + + self._server_configs.add_server_team_role_id_config(role_id) diff --git a/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py b/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py new file mode 100644 index 00000000..da3b7651 --- /dev/null +++ b/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py @@ -0,0 +1,102 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_query.extension import List + +from bot_api.logging.api_logger import ApiLogger +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.technician_config_repository_abc import TechnicianConfigRepositoryABC +from bot_data.model.technician_config import TechnicianConfig +from bot_data.model.technician_id_config import TechnicianIdConfig +from bot_data.model.technician_ping_url_config import TechnicianPingUrlConfig +from bot_data.model.user_role_enum import UserRoleEnum +from bot_graphql.abc.query_abc import QueryABC + + +class TechnicianConfigMutation(QueryABC): + def __init__( + self, + logger: ApiLogger, + bot: DiscordBotServiceABC, + servers: ServerRepositoryABC, + technician_configs: TechnicianConfigRepositoryABC, + db: DatabaseContextABC, + ): + QueryABC.__init__(self, "TechnicianConfigMutation") + + self._logger = logger + self._bot = bot + self._servers = servers + self._technician_configs = technician_configs + self._db = db + + self.set_field("updateTechnicianConfig", self.resolve_update_technician_config) + + def resolve_update_technician_config(self, *_, input: dict): + technician_config = self._technician_configs.get_technician_config() + self._can_user_mutate_data(technician_config, UserRoleEnum.admin) + + technician_config.help_command_reference_url = ( + input["helpCommandReferenceUrl"] + if "helpCommandReferenceUrl" in input + else technician_config.help_command_reference_url + ) + technician_config.wait_for_restart = ( + input["waitForRestart"] if "waitForRestart" in input else technician_config.wait_for_restart + ) + technician_config.wait_for_shutdown = ( + input["waitForShutdown"] if "waitForShutdown" in input else technician_config.wait_for_shutdown + ) + technician_config.cache_max_messages = ( + input["cacheMaxMessages"] if "cacheMaxMessages" in input else technician_config.cache_max_messages + ) + technician_config.ping_urls = ( + List(str, input["pingURLs"]) if "pingURLs" in input else technician_config.ping_urls + ) + technician_config.technician_ids = ( + List(int).extend([int(x) for x in input["technicianIds"]]) + if "technicianIds" in input + else technician_config.technician_ids + ) + + self._technician_configs.update_technician_config(technician_config) + if "pingURLs" in input: + self._update_ping_urls(technician_config) + + if "technicianIds" in input: + self._update_technician_ids(technician_config) + + self._db.save_changes() + return technician_config + + def _update_ping_urls(self, new_config: TechnicianConfig): + old_config = self._technician_configs.get_technician_config() + for url in old_config.ping_urls: + if url in new_config.ping_urls: + continue + + self._technician_configs.delete_technician_ping_url_config(TechnicianPingUrlConfig(url)) + + for url in new_config.ping_urls: + if url in old_config.ping_urls: + continue + + self._technician_configs.add_technician_ping_url_config(TechnicianPingUrlConfig(url)) + + def _update_technician_ids(self, new_config: TechnicianConfig): + old_config = self._technician_configs.get_technician_config() + for technician_id in old_config.technician_ids: + if technician_id in new_config.technician_ids: + continue + + self._technician_configs.delete_technician_id_config(TechnicianIdConfig(technician_id)) + + for technician_id in new_config.technician_ids: + user = self._bot.get_user(technician_id) + if user is None: + raise ValueError(f"Invalid technicianId") + + for technician_id in new_config.technician_ids: + if technician_id in old_config.technician_ids: + continue + + self._technician_configs.add_technician_id_config(TechnicianIdConfig(technician_id)) diff --git a/kdb-bot/src/bot_graphql/mutations/user_joined_game_server_mutation.py b/kdb-bot/src/bot_graphql/mutations/user_joined_game_server_mutation.py index ae0a5c04..62fef010 100644 --- a/kdb-bot/src/bot_graphql/mutations/user_joined_game_server_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/user_joined_game_server_mutation.py @@ -2,6 +2,7 @@ import hashlib from datetime import datetime from typing import Optional +from cpl_core.configuration import ConfigurationABC from cpl_core.database.context import DatabaseContextABC from cpl_core.logging import LoggerABC from cpl_discord.service import DiscordBotServiceABC @@ -15,19 +16,18 @@ from bot_data.abc.user_game_ident_repository_abc import UserGameIdentRepositoryA from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.model.api_key import ApiKey +from bot_data.model.server_config import ServerConfig from bot_data.model.user_joined_game_server import UserJoinedGameServer from bot_data.model.user_role_enum import UserRoleEnum from bot_graphql.abc.query_abc import QueryABC -from modules.base.abc.base_helper_abc import BaseHelperABC -from modules.base.configuration.base_server_settings import BaseServerSettings from modules.permission.service.permission_service import PermissionService class UserJoinedGameServerMutation(QueryABC): def __init__( self, + config: ConfigurationABC, logger: LoggerABC, - base_helper: BaseHelperABC, servers: ServerRepositoryABC, users: UserRepositoryABC, user_joined_game_servers: UserJoinedGameServerRepositoryABC, @@ -41,8 +41,8 @@ class UserJoinedGameServerMutation(QueryABC): ): QueryABC.__init__(self, "UserJoinedGameServerMutation") + self._config = config self._logger = logger - self._base_helper = base_helper self._servers = servers self._users = users self._user_joined_game_servers = user_joined_game_servers @@ -116,7 +116,7 @@ class UserJoinedGameServerMutation(QueryABC): return active.leaved_on = datetime.now() - settings: BaseServerSettings = self._base_helper.get_config(user.server.discord_id) + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{user.server.discord_id}") ontime = round((active.leaved_on - active.joined_on).total_seconds() / 3600, 2) old_xp = user.xp diff --git a/kdb-bot/src/bot_graphql/queries/server_config_query.py b/kdb-bot/src/bot_graphql/queries/server_config_query.py new file mode 100644 index 00000000..8672c4d2 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/server_config_query.py @@ -0,0 +1,39 @@ +from cpl_core.database.context import DatabaseContextABC + +from bot_data.model.server_config_history import ServerConfigHistory +from bot_data.model.team_member_type_enum import TeamMemberTypeEnum +from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC + + +class ServerConfigQuery(DataQueryWithHistoryABC): + def __init__(self, db: DatabaseContextABC): + DataQueryWithHistoryABC.__init__(self, "ServerConfig", "CFG_ServerHistory", ServerConfigHistory, db) + + self.set_field("id", lambda config, *_: config.id) + self.set_field("messageDeleteTimer", lambda config, *_: config.message_delete_timer) + self.set_field("notificationChatId", lambda config, *_: config.notification_chat_id) + self.set_field("maxVoiceStateHours", lambda config, *_: config.max_voice_state_hours) + self.set_field("xpPerMessage", lambda config, *_: config.xp_per_message) + self.set_field("xpPerReaction", lambda config, *_: config.xp_per_reaction) + self.set_field("maxMessageXpPerHour", lambda config, *_: config.max_message_xp_per_hour) + self.set_field("xpPerOntimeHour", lambda config, *_: config.xp_per_ontime_hour) + self.set_field("xpPerEventParticipation", lambda config, *_: config.xp_per_event_participation) + self.set_field("xpPerAchievement", lambda config, *_: config.xp_per_achievement) + self.set_field("afkCommandChannelId", lambda config, *_: config.afk_command_channel_id) + self.set_field("helpVoiceChannelId", lambda config, *_: config.help_voice_channel_id) + self.set_field("teamChannelId", lambda config, *_: config.team_channel_id) + self.set_field("loginMessageChannelId", lambda config, *_: config.login_message_channel_id) + self.set_field("afkChannelIds", lambda config, *_: config.afk_channel_ids) + self.set_field( + "moderatorRoleIds", + lambda config, *_: config.team_role_ids.where( + lambda x: x.team_member_type == TeamMemberTypeEnum.moderator + ).select(lambda x: x.role_id), + ) + self.set_field( + "adminRoleIds", + lambda config, *_: config.team_role_ids.where( + lambda x: x.team_member_type == TeamMemberTypeEnum.admin + ).select(lambda x: x.role_id), + ) + self.set_field("server", lambda config, *_: config.server) diff --git a/kdb-bot/src/bot_graphql/queries/server_query.py b/kdb-bot/src/bot_graphql/queries/server_query.py index 5da12f2d..08c686b5 100644 --- a/kdb-bot/src/bot_graphql/queries/server_query.py +++ b/kdb-bot/src/bot_graphql/queries/server_query.py @@ -6,6 +6,7 @@ from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC from bot_data.abc.client_repository_abc import ClientRepositoryABC from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC from bot_data.abc.level_repository_abc import LevelRepositoryABC +from bot_data.abc.server_config_repository_abc import ServerConfigRepositoryABC from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC from bot_data.abc.user_repository_abc import UserRepositoryABC @@ -32,6 +33,7 @@ class ServerQuery(DataQueryWithHistoryABC): ujs: UserJoinedServerRepositoryABC, ujvs: UserJoinedVoiceChannelRepositoryABC, achievements: AchievementRepositoryABC, + server_configs: ServerConfigRepositoryABC, ): DataQueryWithHistoryABC.__init__(self, "Server", "ServersHistory", ServerHistory, db) @@ -62,6 +64,7 @@ class ServerQuery(DataQueryWithHistoryABC): self.add_collection( "achievement", lambda server, *_: achievements.get_achievements_by_server_id(server.id), AchievementFilter ) + self.set_field("config", lambda server, *_: server_configs.get_server_config_by_server(server.id)) @staticmethod def resolve_id(server: Server, *_): diff --git a/kdb-bot/src/bot_graphql/queries/technician_config_history_query.py b/kdb-bot/src/bot_graphql/queries/technician_config_history_query.py new file mode 100644 index 00000000..8d945fe0 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/technician_config_history_query.py @@ -0,0 +1,11 @@ +from bot_graphql.abc.history_query_abc import HistoryQueryABC + + +class TechnicianConfigHistoryQuery(HistoryQueryABC): + def __init__(self): + HistoryQueryABC.__init__(self, "TechnicianConfig") + + self.set_field("helpCommandReferenceUrl", lambda config, *_: config.help_command_reference_url) + self.set_field("waitForRestart", lambda config, *_: config.wait_for_restart) + self.set_field("waitForShutdown", lambda config, *_: config.wait_for_shutdown) + self.set_field("cacheMaxMessages", lambda config, *_: config.cache_max_messages) diff --git a/kdb-bot/src/bot_graphql/queries/technician_config_query.py b/kdb-bot/src/bot_graphql/queries/technician_config_query.py new file mode 100644 index 00000000..3cda423f --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/technician_config_query.py @@ -0,0 +1,57 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_query.extension import List + +from bot_data.abc.table_with_id_abc import TableWithIdABC +from bot_data.model.technician_config_history import TechnicianConfigHistory +from bot_data.model.technician_id_config_history import TechnicianIdConfigHistory +from bot_data.model.technician_ping_url_config_history import TechnicianPingUrlConfigHistory +from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC + + +class TechnicianConfigQuery(DataQueryWithHistoryABC): + def __init__(self, db: DatabaseContextABC): + DataQueryWithHistoryABC.__init__(self, "TechnicianConfig", "CFG_TechnicianHistory", TechnicianConfigHistory, db) + + self.set_field("helpCommandReferenceUrl", lambda config, *_: config.help_command_reference_url) + self.set_field("waitForRestart", lambda config, *_: config.wait_for_restart) + self.set_field("waitForShutdown", lambda config, *_: config.wait_for_shutdown) + self.set_field("cacheMaxMessages", lambda config, *_: config.cache_max_messages) + self.set_field("pingURLs", lambda config, *_: config.ping_urls) + self.set_field("technicianIds", lambda config, *_: config.technician_ids) + + self.set_field("pingURLHistory", self.resolve_ping_url_history) + self.set_field("technicianIdHistory", self.resolve_technician_id_history) + + def resolve_ping_url_history(self, entry: TableWithIdABC, *_): + history = List(TechnicianPingUrlConfigHistory) + + results = self._db.select( + f""" + SELECT * + FROM CFG_TechnicianPingUrlsHistory + WHERE Id = {entry.id} + ORDER BY DateTo DESC; + """ + ) + + for result in results: + history.add(TechnicianPingUrlConfigHistory(*result[1:], result[0])) + + return history + + def resolve_technician_id_history(self, entry: TableWithIdABC, *_): + history = List(TechnicianIdConfigHistory) + + results = self._db.select( + f""" + SELECT * + FROM CFG_TechnicianIdsHistory + WHERE Id = {entry.id} + ORDER BY DateTo DESC; + """ + ) + + for result in results: + history.add(TechnicianIdConfigHistory(*result[1:], result[0])) + + return history diff --git a/kdb-bot/src/bot_graphql/queries/technician_id_config_history_query.py b/kdb-bot/src/bot_graphql/queries/technician_id_config_history_query.py new file mode 100644 index 00000000..6ab0a3a3 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/technician_id_config_history_query.py @@ -0,0 +1,8 @@ +from bot_graphql.abc.history_query_abc import HistoryQueryABC + + +class TechnicianIdConfigHistoryQuery(HistoryQueryABC): + def __init__(self): + HistoryQueryABC.__init__(self, "TechnicianIdConfig") + + self.set_field("technicianId", lambda config, *_: config.technicianId) diff --git a/kdb-bot/src/bot_graphql/queries/technician_ping_url_config_history_query.py b/kdb-bot/src/bot_graphql/queries/technician_ping_url_config_history_query.py new file mode 100644 index 00000000..4be66b6c --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/technician_ping_url_config_history_query.py @@ -0,0 +1,8 @@ +from bot_graphql.abc.history_query_abc import HistoryQueryABC + + +class TechnicianPingUrlConfigHistoryQuery(HistoryQueryABC): + def __init__(self): + HistoryQueryABC.__init__(self, "TechnicianPingUrlConfig") + + self.set_field("url", lambda config, *_: config.ping_url) diff --git a/kdb-bot/src/bot_graphql/query.py b/kdb-bot/src/bot_graphql/query.py index 5c1d2263..030d7bdd 100644 --- a/kdb-bot/src/bot_graphql/query.py +++ b/kdb-bot/src/bot_graphql/query.py @@ -7,6 +7,7 @@ from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC from bot_data.abc.level_repository_abc import LevelRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.technician_config_repository_abc import TechnicianConfigRepositoryABC from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC @@ -41,6 +42,7 @@ class Query(QueryABC): users: UserRepositoryABC, achievements: AchievementRepositoryABC, achievement_service: AchievementService, + technician_config: TechnicianConfigRepositoryABC, ): QueryABC.__init__(self, "Query") @@ -68,6 +70,7 @@ class Query(QueryABC): ) self.add_collection("user", lambda *_: users.get_users(), UserFilter) self.add_collection("achievement", lambda *_: achievements.get_achievements(), AchievementFilter) + self.set_field("technicianConfig", lambda *_: technician_config.get_technician_config()) self.set_field("guilds", self._resolve_guilds) self.set_field("achievementAttributes", lambda x, *_: achievement_service.get_attributes()) diff --git a/kdb-bot/src/modules/achievements/achievement_service.py b/kdb-bot/src/modules/achievements/achievement_service.py index fe875965..9a5af106 100644 --- a/kdb-bot/src/modules/achievements/achievement_service.py +++ b/kdb-bot/src/modules/achievements/achievement_service.py @@ -5,16 +5,15 @@ from cpl_discord.service import DiscordBotServiceABC from cpl_query.extension import List from cpl_translation import TranslatePipe -from bot_core.configuration.server_settings import ServerSettings from bot_core.service.message_service import MessageService from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.model.achievement import Achievement +from bot_data.model.server_config import ServerConfig from bot_data.model.user import User from bot_data.model.user_got_achievement import UserGotAchievement from modules.achievements.achievement_attribute_resolver import AchievementAttributeResolver from modules.achievements.model.achievement_attribute import AchievementAttribute -from modules.base.configuration.base_server_settings import BaseServerSettings class AchievementService: @@ -100,7 +99,7 @@ class AchievementService: await self._send_achievement_notification(user.server.discord_id, user.discord_id, achievement.name) def _give_user_xp(self, user: User): - settings: BaseServerSettings = self._config.get_configuration(f"BaseServerSettings_{user.server.discord_id}") + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{user.server.discord_id}") user.xp += settings.xp_per_achievement self._users.update_user(user) self._db.save_changes() @@ -108,7 +107,7 @@ class AchievementService: async def _send_achievement_notification(self, guild_id: int, member_id: int, achievement_name: str): member = self._bot.get_guild(guild_id).get_member(member_id) - settings: ServerSettings = self._config.get_configuration(f"ServerSettings_{guild_id}") + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{guild_id}") await self._message_service.send_channel_message( self._bot.get_channel(settings.notification_chat_id), self._t.transform("modules.achievements.got_new_achievement").format(member.mention, achievement_name), diff --git a/kdb-bot/src/modules/base/abc/__init__.py b/kdb-bot/src/modules/base/abc/__init__.py deleted file mode 100644 index 971d0324..00000000 --- a/kdb-bot/src/modules/base/abc/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -bot Keksdose bot -~~~~~~~~~~~~~~~~~~~ - -Discord bot for the Keksdose discord Server - -:copyright: (c) 2022 - 2023 sh-edraft.de -:license: MIT, see LICENSE for more details. - -""" - -__title__ = "modules.base.abc" -__author__ = "Sven Heidemann" -__license__ = "MIT" -__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "1.0.7" - -from collections import namedtuple - - -# imports: - -VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="1", minor="0", micro="7") diff --git a/kdb-bot/src/modules/base/abc/base_helper_abc.py b/kdb-bot/src/modules/base/abc/base_helper_abc.py deleted file mode 100644 index c62fe210..00000000 --- a/kdb-bot/src/modules/base/abc/base_helper_abc.py +++ /dev/null @@ -1,12 +0,0 @@ -from abc import abstractmethod, ABC - -from modules.base.configuration.base_server_settings import BaseServerSettings - - -class BaseHelperABC(ABC): - def __init__(self): - ABC.__init__(self) - - @abstractmethod - def get_config(self, g_id: int) -> BaseServerSettings: - pass diff --git a/kdb-bot/src/modules/base/base_module.py b/kdb-bot/src/modules/base/base_module.py index aad5292d..ebc26801 100644 --- a/kdb-bot/src/modules/base/base_module.py +++ b/kdb-bot/src/modules/base/base_module.py @@ -6,7 +6,6 @@ from cpl_discord.service.discord_collection_abc import DiscordCollectionABC from bot_core.abc.module_abc import ModuleABC from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum -from modules.base.abc.base_helper_abc import BaseHelperABC from modules.base.command.afk_command import AFKCommand from modules.base.command.game_server_group import GameServerGroup from modules.base.command.help_command import HelpCommand @@ -40,7 +39,6 @@ from modules.base.events.base_on_voice_state_update_event_scheduled_event_bonus from modules.base.forms.bug_report_form import BugReportForm from modules.base.forms.complaint_form import ComplaintForm from modules.base.helper.base_reaction_handler import BaseReactionHandler -from modules.base.service.base_helper_service import BaseHelperService from modules.base.service.event_service import EventService from modules.base.service.user_warnings_service import UserWarningsService @@ -53,7 +51,6 @@ class BaseModule(ModuleABC): pass def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): - services.add_transient(BaseHelperABC, BaseHelperService) services.add_transient(BaseReactionHandler) services.add_singleton(EventService) services.add_transient(UserWarningsService) diff --git a/kdb-bot/src/modules/base/command/afk_command.py b/kdb-bot/src/modules/base/command/afk_command.py index 7d05f712..cf7f478e 100644 --- a/kdb-bot/src/modules/base/command/afk_command.py +++ b/kdb-bot/src/modules/base/command/afk_command.py @@ -10,7 +10,6 @@ from bot_core.abc.client_utils_abc import ClientUtilsABC from bot_core.abc.message_service_abc import MessageServiceABC from bot_core.helper.command_checks import CommandChecks from bot_core.logging.command_logger import CommandLogger -from modules.base.configuration.base_server_settings import BaseServerSettings class AFKCommand(DiscordCommandABC): @@ -39,7 +38,7 @@ class AFKCommand(DiscordCommandABC): @CommandChecks.check_is_ready() async def afk(self, ctx: Context): self._logger.debug(__name__, f"Received command afk {ctx}") - settings: BaseServerSettings = self._config.get_configuration(f"BaseServerSettings_{ctx.guild.id}") + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{ctx.guild.id}") if ctx.author.voice is None or ctx.author.voice.channel is None: await self._message_service.send_ctx_msg( diff --git a/kdb-bot/src/modules/base/command/help_command.py b/kdb-bot/src/modules/base/command/help_command.py index 9c37cf08..5fa3ac83 100644 --- a/kdb-bot/src/modules/base/command/help_command.py +++ b/kdb-bot/src/modules/base/command/help_command.py @@ -12,7 +12,6 @@ from bot_core.abc.client_utils_abc import ClientUtilsABC from bot_core.abc.message_service_abc import MessageServiceABC from bot_core.helper.command_checks import CommandChecks from bot_core.logging.command_logger import CommandLogger -from modules.base.configuration.base_server_settings import BaseServerSettings class HelpCommand(DiscordCommandABC): @@ -39,7 +38,7 @@ class HelpCommand(DiscordCommandABC): @CommandChecks.check_is_ready() async def help(self, ctx: Context, persistent_flag: str = None): self._logger.debug(__name__, f"Received command help {ctx}:{persistent_flag}") - settings: BaseServerSettings = self._config.get_configuration(f"BaseServerSettings_{ctx.guild.id}") + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{ctx.guild.id}") is_persistent = persistent_flag == "--stay" await self._message_service.send_ctx_msg( ctx, diff --git a/kdb-bot/src/modules/base/command/ping_command.py b/kdb-bot/src/modules/base/command/ping_command.py index eaf58ff6..ca0a14ac 100644 --- a/kdb-bot/src/modules/base/command/ping_command.py +++ b/kdb-bot/src/modules/base/command/ping_command.py @@ -10,8 +10,7 @@ from bot_core.abc.message_service_abc import MessageServiceABC from bot_core.helper.command_checks import CommandChecks from bot_core.logging.command_logger import CommandLogger from bot_data.abc.server_repository_abc import ServerRepositoryABC -from modules.base.abc.base_helper_abc import BaseHelperABC -from modules.base.configuration.base_server_settings import BaseServerSettings +from bot_data.model.technician_config import TechnicianConfig from modules.permission.abc.permission_service_abc import PermissionServiceABC @@ -24,8 +23,8 @@ class PingCommand(DiscordCommandABC): client_utils: ClientUtilsABC, translate: TranslatePipe, permissions: PermissionServiceABC, - base_helper: BaseHelperABC, servers: ServerRepositoryABC, + settings: TechnicianConfig, ): DiscordCommandABC.__init__(self) @@ -35,8 +34,8 @@ class PingCommand(DiscordCommandABC): self._client_utils = client_utils self._t = translate self._permissions = permissions - self._base_helper = base_helper self._servers = servers + self._settings = settings self._logger.trace(__name__, f"Loaded command service: {type(self).__name__}") @@ -58,9 +57,7 @@ class PingCommand(DiscordCommandABC): description=self._t.transform("modules.base.info.description"), color=int("ef9d0d", 16), ) - server = self._servers.get_server_by_discord_id(ctx.guild.id) - settings: BaseServerSettings = self._base_helper.get_config(server.discord_id) - for server in settings.ping_urls: + for server in self._settings.ping_urls: embed.add_field(name=server, value=f"{self._get_ping(server)} ms", inline=False) await self._message_service.send_ctx_msg(ctx, embed) else: diff --git a/kdb-bot/src/modules/base/command/purge_command.py b/kdb-bot/src/modules/base/command/purge_command.py index 60a0ad23..9816e29f 100644 --- a/kdb-bot/src/modules/base/command/purge_command.py +++ b/kdb-bot/src/modules/base/command/purge_command.py @@ -8,9 +8,9 @@ from discord.ext.commands import Context from bot_core.abc.client_utils_abc import ClientUtilsABC from bot_core.abc.message_service_abc import MessageServiceABC -from bot_core.configuration.server_settings import ServerSettings from bot_core.helper.command_checks import CommandChecks from bot_core.logging.command_logger import CommandLogger +from bot_data.model.server_config import ServerConfig from modules.permission.abc.permission_service_abc import PermissionServiceABC @@ -41,7 +41,7 @@ class PurgeCommand(DiscordCommandABC): @CommandChecks.check_is_member_moderator() async def purge(self, ctx: Context): self._logger.debug(__name__, f"Received command purge {ctx}") - server_settings: ServerSettings = self._config.get_configuration(f"ServerSettings_{ctx.guild.id}") + server_settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{ctx.guild.id}") await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.moderator.purge_message")) await asyncio.sleep(server_settings.message_delete_timer) diff --git a/kdb-bot/src/modules/base/configuration/__init__.py b/kdb-bot/src/modules/base/configuration/__init__.py deleted file mode 100644 index bbec5538..00000000 --- a/kdb-bot/src/modules/base/configuration/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -bot Keksdose bot -~~~~~~~~~~~~~~~~~~~ - -Discord bot for the Keksdose discord Server - -:copyright: (c) 2022 - 2023 sh-edraft.de -:license: MIT, see LICENSE for more details. - -""" - -__title__ = "modules.base.configuration" -__author__ = "Sven Heidemann" -__license__ = "MIT" -__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "1.0.7" - -from collections import namedtuple - - -# imports: - -VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="1", minor="0", micro="7") diff --git a/kdb-bot/src/modules/base/configuration/base_server_settings.py b/kdb-bot/src/modules/base/configuration/base_server_settings.py deleted file mode 100644 index 8bd987b4..00000000 --- a/kdb-bot/src/modules/base/configuration/base_server_settings.py +++ /dev/null @@ -1,104 +0,0 @@ -import traceback - -from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console -from cpl_query.extension import List - - -class BaseServerSettings(ConfigurationModelABC): - def __init__(self): - ConfigurationModelABC.__init__(self) - - self._id: int = 0 - self._max_voice_state_hours: int = 0 - self._xp_per_message: int = 0 - self._xp_per_reaction: int = 0 - self._max_message_xp_per_hour: int = 0 - self._xp_per_ontime_hour: int = 0 - self._xp_per_event_participation: int = 0 - self._xp_per_achievement: int = 0 - self._afk_channel_ids: List[int] = List(int) - self._afk_command_channel_id: int = 0 - self._help_command_reference_url: str = "" - self._help_voice_channel_id: int = 0 - self._team_channel_id: int = 0 - self._ping_urls = List(str) - - @property - def id(self) -> int: - return self._id - - @property - def max_voice_state_hours(self) -> int: - return self._max_voice_state_hours - - @property - def xp_per_message(self) -> int: - return self._xp_per_message - - @property - def xp_per_reaction(self) -> int: - return self._xp_per_reaction - - @property - def max_message_xp_per_hour(self) -> int: - return self._max_message_xp_per_hour - - @property - def xp_per_ontime_hour(self) -> int: - return self._xp_per_ontime_hour - - @property - def xp_per_event_participation(self) -> int: - return self._xp_per_event_participation - - @property - def xp_per_achievement(self) -> int: - return self._xp_per_achievement - - @property - def afk_channel_ids(self) -> List[int]: - return self._afk_channel_ids - - @property - def afk_command_channel_id(self) -> int: - return self._afk_command_channel_id - - @property - def help_command_reference_url(self) -> str: - return self._help_command_reference_url - - @property - def team_channel_id(self) -> int: - return self._team_channel_id - - @property - def help_voice_channel_id(self) -> int: - return self._help_voice_channel_id - - @property - def ping_urls(self) -> List[str]: - return self._ping_urls - - def from_dict(self, settings: dict): - try: - self._id = int(settings["Id"]) - self._max_voice_state_hours = int(settings["MaxVoiceStateHours"]) - self._xp_per_message = int(settings["XpPerMessage"]) - self._xp_per_reaction = int(settings["XpPerReaction"]) - self._max_message_xp_per_hour = int(settings["MaxMessageXpPerHour"]) - self._xp_per_ontime_hour = int(settings["XpPerOntimeHour"]) - self._xp_per_event_participation = ( - 0 if "XpPerEventParticipation" not in settings else settings["XpPerEventParticipation"] - ) - for index in settings["AFKChannelIds"]: - self._afk_channel_ids.append(int(index)) - self._afk_command_channel_id = settings["AFKCommandChannelId"] - self._help_command_reference_url = settings["HelpCommandReferenceUrl"] - self._help_voice_channel_id = settings["HelpVoiceChannelId"] - self._team_channel_id = settings["TeamChannelId"] - for url in settings["PingURLs"]: - self._ping_urls.append(url) - except Exception as e: - Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings") - Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") diff --git a/kdb-bot/src/modules/base/configuration/base_settings.py b/kdb-bot/src/modules/base/configuration/base_settings.py deleted file mode 100644 index 0c74132c..00000000 --- a/kdb-bot/src/modules/base/configuration/base_settings.py +++ /dev/null @@ -1,31 +0,0 @@ -import traceback - -from cpl_core.configuration import ConfigurationModelABC -from cpl_core.console import Console -from cpl_query.extension import List - -from modules.base.configuration.base_server_settings import BaseServerSettings - - -class BaseSettings(ConfigurationModelABC): - def __init__(self): - ConfigurationModelABC.__init__(self) - - self._servers: List[BaseServerSettings] = List() - - @property - def servers(self) -> List[BaseServerSettings]: - return self._servers - - def from_dict(self, settings: dict): - try: - servers = List(BaseServerSettings) - for s in settings: - st = BaseServerSettings() - settings[s]["Id"] = s - st.from_dict(settings[s]) - servers.append(st) - self._servers = servers - except Exception as e: - Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings") - Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") diff --git a/kdb-bot/src/modules/base/events/base_on_command_error_event.py b/kdb-bot/src/modules/base/events/base_on_command_error_event.py index c9c4dcc8..f47dbb85 100644 --- a/kdb-bot/src/modules/base/events/base_on_command_error_event.py +++ b/kdb-bot/src/modules/base/events/base_on_command_error_event.py @@ -1,18 +1,15 @@ import datetime -import traceback import uuid +from cpl_core.logging import LoggerABC from cpl_core.time import TimeFormatSettings +from cpl_discord.events.on_command_error_abc import OnCommandErrorABC from cpl_discord.service import DiscordBotServiceABC from cpl_translation import TranslatePipe from discord.ext import commands from discord.ext.commands import Context, CommandError -from cpl_core.logging import LoggerABC -from cpl_discord.events.on_command_error_abc import OnCommandErrorABC - from bot_core.abc.message_service_abc import MessageServiceABC -from bot_core.configuration.bot_settings import BotSettings from bot_core.exception.check_error import CheckError @@ -22,7 +19,6 @@ class BaseOnCommandErrorEvent(OnCommandErrorABC): logger: LoggerABC, bot: DiscordBotServiceABC, messenger: MessageServiceABC, - bot_settings: BotSettings, time_format_settings: TimeFormatSettings, translate: TranslatePipe, ): diff --git a/kdb-bot/src/modules/base/events/base_on_command_event.py b/kdb-bot/src/modules/base/events/base_on_command_event.py index 14ff7287..4f33abd9 100644 --- a/kdb-bot/src/modules/base/events/base_on_command_event.py +++ b/kdb-bot/src/modules/base/events/base_on_command_event.py @@ -9,14 +9,11 @@ from cpl_translation import TranslatePipe from discord.ext.commands import Context from bot_core.abc.message_service_abc import MessageServiceABC -from bot_core.configuration.bot_settings import BotSettings from bot_core.logging.command_logger import CommandLogger from bot_data.abc.client_repository_abc import ClientRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.model.user import User -from modules.base.abc.base_helper_abc import BaseHelperABC -from modules.base.configuration.base_server_settings import BaseServerSettings class BaseOnCommandEvent(OnCommandABC): @@ -25,10 +22,8 @@ class BaseOnCommandEvent(OnCommandABC): logger: CommandLogger, bot: DiscordBotServiceABC, messenger: MessageServiceABC, - bot_settings: BotSettings, time_format_settings: TimeFormatSettings, translate: TranslatePipe, - bhs: BaseHelperABC, db: DatabaseContextABC, users: UserRepositoryABC, clients: ClientRepositoryABC, @@ -38,10 +33,8 @@ class BaseOnCommandEvent(OnCommandABC): self._logger = logger self._bot = bot self._messenger = messenger - self._bot_settings = bot_settings self._time_format_settings = time_format_settings self._t = translate - self._base_helper = bhs self._db = db self._users = users self._clients = clients @@ -73,7 +66,7 @@ class BaseOnCommandEvent(OnCommandABC): self._logger.error(__name__, f"User not found {dc_user_id}") return - settings: BaseServerSettings = self._base_helper.get_config(message.guild.id) + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{message.guild.id}") old_xp = user.xp user.xp += settings.xp_per_message self._users.update_user(user) diff --git a/kdb-bot/src/modules/base/events/base_on_member_join_event.py b/kdb-bot/src/modules/base/events/base_on_member_join_event.py index 3acfe4aa..8f8007f5 100644 --- a/kdb-bot/src/modules/base/events/base_on_member_join_event.py +++ b/kdb-bot/src/modules/base/events/base_on_member_join_event.py @@ -17,8 +17,6 @@ from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.model.known_user import KnownUser from bot_data.model.user import User from bot_data.model.user_joined_server import UserJoinedServer -from modules.base.abc.base_helper_abc import BaseHelperABC -from modules.base.configuration.base_server_settings import BaseServerSettings from modules.permission.abc.permission_service_abc import PermissionServiceABC @@ -27,7 +25,6 @@ class BaseOnMemberJoinEvent(OnMemberJoinABC): self, config: ConfigurationABC, logger: LoggerABC, - base_helper: BaseHelperABC, messenger: MessageServiceABC, permissions: PermissionServiceABC, db: DatabaseContextABC, @@ -40,7 +37,6 @@ class BaseOnMemberJoinEvent(OnMemberJoinABC): OnMemberJoinABC.__init__(self) self._config = config self._logger = logger - self._base_helper = base_helper self._messenger = messenger self._permission_service = permissions self._db = db @@ -65,7 +61,6 @@ class BaseOnMemberJoinEvent(OnMemberJoinABC): async def _add_if_not_exists_user_async(self, member: Union[discord.User, discord.Member]): self._logger.debug(__name__, f"Check if user exists {member}") - settings: BaseServerSettings = self._base_helper.get_config(member.guild.id) await self._messenger.send_dm_message( self._t.transform("modules.base.welcome_message").format(member.guild.name), member, diff --git a/kdb-bot/src/modules/base/events/base_on_member_remove_event.py b/kdb-bot/src/modules/base/events/base_on_member_remove_event.py index 211f8c57..8e565267 100644 --- a/kdb-bot/src/modules/base/events/base_on_member_remove_event.py +++ b/kdb-bot/src/modules/base/events/base_on_member_remove_event.py @@ -12,15 +12,12 @@ from bot_core.helper.event_checks import EventChecks from bot_data.abc.server_repository_abc import ServerRepositoryABC from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC from bot_data.abc.user_repository_abc import UserRepositoryABC -from modules.base.abc.base_helper_abc import BaseHelperABC -from modules.base.configuration.base_server_settings import BaseServerSettings class BaseOnMemberRemoveEvent(OnMemberRemoveABC): def __init__( self, logger: LoggerABC, - base_helper: BaseHelperABC, db: DatabaseContextABC, messenger: MessageServiceABC, users: UserRepositoryABC, @@ -41,7 +38,7 @@ class BaseOnMemberRemoveEvent(OnMemberRemoveABC): async def _remove_user(self, member: Union[discord.User, discord.Member]): self._logger.debug(__name__, f"Remove user {member}") - settings: BaseServerSettings = self._base_helper.get_config(member.guild.id) + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{member.guild.id}") await self._messenger.send_dm_message(self._t.transform("modules.base.goodbye_message"), member) try: diff --git a/kdb-bot/src/modules/base/events/base_on_message_delete_event.py b/kdb-bot/src/modules/base/events/base_on_message_delete_event.py index 6320269a..afd065a8 100644 --- a/kdb-bot/src/modules/base/events/base_on_message_delete_event.py +++ b/kdb-bot/src/modules/base/events/base_on_message_delete_event.py @@ -11,15 +11,12 @@ from bot_data.abc.client_repository_abc import ClientRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.model.user import User -from modules.base.abc.base_helper_abc import BaseHelperABC -from modules.base.configuration.base_server_settings import BaseServerSettings class BaseOnMessageDeleteEvent(OnMessageDeleteABC): def __init__( self, logger: MessageLogger, - bhs: BaseHelperABC, db: DatabaseContextABC, bot: DiscordBotServiceABC, users: UserRepositoryABC, @@ -28,7 +25,6 @@ class BaseOnMessageDeleteEvent(OnMessageDeleteABC): ): OnMessageDeleteABC.__init__(self) self._logger = logger - self._base_helper = bhs self._db = db self._bot = bot self._users = users @@ -61,7 +57,7 @@ class BaseOnMessageDeleteEvent(OnMessageDeleteABC): self._logger.error(__name__, f"User not found {dc_user_id}") return - settings: BaseServerSettings = self._base_helper.get_config(message.guild.id) + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{message.guild.id}") old_xp = user.xp user.xp -= settings.xp_per_message self._users.update_user(user) diff --git a/kdb-bot/src/modules/base/events/base_on_message_event.py b/kdb-bot/src/modules/base/events/base_on_message_event.py index 72637252..61789132 100644 --- a/kdb-bot/src/modules/base/events/base_on_message_event.py +++ b/kdb-bot/src/modules/base/events/base_on_message_event.py @@ -12,16 +12,14 @@ from bot_core.service.client_utils_service import ClientUtilsService from bot_data.abc.client_repository_abc import ClientRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.model.server_config import ServerConfig from bot_data.model.user import User -from modules.base.abc.base_helper_abc import BaseHelperABC -from modules.base.configuration.base_server_settings import BaseServerSettings class BaseOnMessageEvent(OnMessageABC): def __init__( self, logger: MessageLogger, - bhs: BaseHelperABC, client_utils: ClientUtilsService, db: DatabaseContextABC, bot: DiscordBotServiceABC, @@ -31,7 +29,6 @@ class BaseOnMessageEvent(OnMessageABC): ): OnMessageABC.__init__(self) self._logger = logger - self._base_helper = bhs self._client_utils = client_utils self._bot = bot self._db = db @@ -66,7 +63,7 @@ class BaseOnMessageEvent(OnMessageABC): self._logger.error(__name__, f"User not found {dc_user_id}") return - settings: BaseServerSettings = self._base_helper.get_config(message.guild.id) + settings: ServerConfig = se if self._client_utils.is_message_xp_count_by_hour_higher_that_max_message_count_per_hour( message.created_at, user, settings ): diff --git a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py index 52e0b551..6fb0c113 100644 --- a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py +++ b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py @@ -16,10 +16,9 @@ from bot_data.abc.user_joined_voice_channel_repository_abc import ( ) from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.model.server import Server +from bot_data.model.server_config import ServerConfig from bot_data.model.user import User from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel -from modules.base.abc.base_helper_abc import BaseHelperABC -from modules.base.configuration.base_server_settings import BaseServerSettings class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): @@ -27,7 +26,6 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): self, config: ConfigurationABC, logger: LoggerABC, - base_helper: BaseHelperABC, servers: ServerRepositoryABC, known_users: KnownUserRepositoryABC, users: UserRepositoryABC, @@ -38,7 +36,6 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): OnVoiceStateUpdateABC.__init__(self) self._config = config self._logger = logger - self._base_helper = base_helper self._servers = servers self._known_users = known_users self._users = users @@ -67,7 +64,7 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): self._db.save_changes() return - settings: BaseServerSettings = self._base_helper.get_config(server.discord_id) + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{server.discord_id}") join = self._user_joins_vc.get_active_user_joined_voice_channel_by_user_id(user.id) join.leaved_on = datetime.now() @@ -98,7 +95,7 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): __name__, f"Detected on_voice_state_update {member.id} from {before} to {after}", ) - settings: BaseServerSettings = self._base_helper.get_config(member.guild.id) + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{member.guild.id}") server = self._servers.get_server_by_discord_id(member.guild.id) try: diff --git a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_help_channel.py b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_help_channel.py index 4f640ff0..5bcd1f95 100644 --- a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_help_channel.py +++ b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_help_channel.py @@ -7,8 +7,7 @@ from cpl_translation import TranslatePipe from bot_core.abc.message_service_abc import MessageServiceABC from bot_core.helper.event_checks import EventChecks from bot_data.abc.server_repository_abc import ServerRepositoryABC -from modules.base.abc.base_helper_abc import BaseHelperABC -from modules.base.configuration.base_server_settings import BaseServerSettings +from bot_data.model.server_config import ServerConfig from modules.permission.abc.permission_service_abc import PermissionServiceABC @@ -17,7 +16,6 @@ class BaseOnVoiceStateUpdateEventHelpChannel(OnVoiceStateUpdateABC): self, config: ConfigurationABC, logger: LoggerABC, - base_helper: BaseHelperABC, servers: ServerRepositoryABC, permissions: PermissionServiceABC, message_service: MessageServiceABC, @@ -26,7 +24,6 @@ class BaseOnVoiceStateUpdateEventHelpChannel(OnVoiceStateUpdateABC): OnVoiceStateUpdateABC.__init__(self) self._config = config self._logger = logger - self._base_helper = base_helper self._servers = servers self._permissions = permissions self._message_service = message_service @@ -43,7 +40,7 @@ class BaseOnVoiceStateUpdateEventHelpChannel(OnVoiceStateUpdateABC): ): self._logger.debug(__name__, f"Module {type(self)} started") server = self._servers.get_server_by_discord_id(member.guild.id) - settings: BaseServerSettings = self._base_helper.get_config(server.discord_id) + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{server.discord_id}") if after.channel is None or after.channel.id != settings.help_voice_channel_id: return diff --git a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_scheduled_event_bonus.py b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_scheduled_event_bonus.py index d8283652..e5838cec 100644 --- a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_scheduled_event_bonus.py +++ b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_scheduled_event_bonus.py @@ -7,8 +7,7 @@ from cpl_discord.events import OnVoiceStateUpdateABC from bot_core.helper.event_checks import EventChecks from bot_data.abc.server_repository_abc import ServerRepositoryABC from bot_data.abc.user_repository_abc import UserRepositoryABC -from modules.base.abc.base_helper_abc import BaseHelperABC -from modules.base.configuration.base_server_settings import BaseServerSettings +from bot_data.model.server_config import ServerConfig from modules.base.service.event_service import EventService @@ -17,7 +16,6 @@ class BaseOnVoiceStateUpdateEventScheduledEventBonus(OnVoiceStateUpdateABC): self, config: ConfigurationABC, logger: LoggerABC, - base_helper: BaseHelperABC, servers: ServerRepositoryABC, users: UserRepositoryABC, events: EventService, @@ -26,7 +24,6 @@ class BaseOnVoiceStateUpdateEventScheduledEventBonus(OnVoiceStateUpdateABC): OnVoiceStateUpdateABC.__init__(self) self._config = config self._logger = logger - self._base_helper = base_helper self._servers = servers self._users = users self._events = events @@ -57,7 +54,7 @@ class BaseOnVoiceStateUpdateEventScheduledEventBonus(OnVoiceStateUpdateABC): self._logger.debug(__name__, f"Module {type(self)} stopped") return - settings: BaseServerSettings = self._base_helper.get_config(server.discord_id) + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{server.discord_id}") user.xp += settings.xp_per_event_participation self._users.update_user(user) self._db.save_changes() diff --git a/kdb-bot/src/modules/base/forms/bug_report_form.py b/kdb-bot/src/modules/base/forms/bug_report_form.py index 85d24bce..185fd51f 100644 --- a/kdb-bot/src/modules/base/forms/bug_report_form.py +++ b/kdb-bot/src/modules/base/forms/bug_report_form.py @@ -5,9 +5,8 @@ from cpl_translation import TranslatePipe from discord import ui, TextStyle from bot_core.abc.message_service_abc import MessageServiceABC -from bot_core.configuration.bot_settings import BotSettings from bot_core.logging.command_logger import CommandLogger -from modules.base.service.base_helper_service import BaseHelperService +from bot_data.model.technician_config import TechnicianConfig class BugReportForm(ui.Modal): @@ -15,22 +14,20 @@ class BugReportForm(ui.Modal): def __init__( self, - bot_settings: BotSettings, + technician_config: TechnicianConfig, bot: DiscordBotServiceABC, db: DatabaseContextABC, logger: CommandLogger, message_service: MessageServiceABC, - base_helper: BaseHelperService, t: TranslatePipe, ): ui.Modal.__init__(self, title=t.transform("modules.base.bug.title")) - self._bot_settings = bot_settings + self._technician_config = technician_config self._bot = bot self._db = db self._message_service = message_service self._logger = logger - self._base_helper = base_helper self._t = t self.description.label = t.transform("modules.base.bug.label") @@ -38,7 +35,7 @@ class BugReportForm(ui.Modal): async def on_submit(self, interaction: discord.Interaction): self._logger.debug(__name__, f"Started bug report form") - for t in self._bot_settings.technicians: + for t in self._technician_config.technician_ids: member = self._bot.get_user(t) await self._message_service.send_dm_message( self._t.transform("modules.base.bug.message").format(interaction.user.mention, self.description.value), diff --git a/kdb-bot/src/modules/base/forms/complaint_form.py b/kdb-bot/src/modules/base/forms/complaint_form.py index 6ae3b96e..b0d77813 100644 --- a/kdb-bot/src/modules/base/forms/complaint_form.py +++ b/kdb-bot/src/modules/base/forms/complaint_form.py @@ -1,12 +1,12 @@ import discord +from cpl_core.configuration import ConfigurationABC from cpl_core.database.context import DatabaseContextABC from cpl_translation import TranslatePipe from discord import ui, TextStyle from bot_core.abc.message_service_abc import MessageServiceABC from bot_core.logging.command_logger import CommandLogger -from modules.base.configuration.base_server_settings import BaseServerSettings -from modules.base.service.base_helper_service import BaseHelperService +from bot_data.model.server_config import ServerConfig class ComplaintForm(ui.Modal): @@ -14,25 +14,25 @@ class ComplaintForm(ui.Modal): def __init__( self, + config: ConfigurationABC, db: DatabaseContextABC, logger: CommandLogger, message_service: MessageServiceABC, - base_helper: BaseHelperService, t: TranslatePipe, ): ui.Modal.__init__(self, title=t.transform("modules.base.complaints.title")) + self._config = config self._db = db self._message_service = message_service self._logger = logger - self._base_helper = base_helper self._t = t self.description.label = t.transform("modules.base.complaints.label") async def on_submit(self, interaction: discord.Interaction): self._logger.debug(__name__, f"Started complaint command form") - settings: BaseServerSettings = self._base_helper.get_config(interaction.guild.id) + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{interaction.guild.id}") channel = interaction.guild.get_channel(settings.team_channel_id) await self._message_service.send_channel_message( channel, diff --git a/kdb-bot/src/modules/base/helper/base_reaction_handler.py b/kdb-bot/src/modules/base/helper/base_reaction_handler.py index a16c2cf4..d2cb1581 100644 --- a/kdb-bot/src/modules/base/helper/base_reaction_handler.py +++ b/kdb-bot/src/modules/base/helper/base_reaction_handler.py @@ -1,5 +1,6 @@ from datetime import datetime +from cpl_core.configuration import ConfigurationABC from cpl_core.database.context import DatabaseContextABC from cpl_discord.service import DiscordBotServiceABC from discord import RawReactionActionEvent @@ -9,26 +10,25 @@ from bot_core.helper.log_message_helper import LogMessageHelper from bot_core.logging.message_logger import MessageLogger from bot_data.abc.server_repository_abc import ServerRepositoryABC from bot_data.abc.user_repository_abc import UserRepositoryABC -from modules.base.abc.base_helper_abc import BaseHelperABC -from modules.base.configuration.base_server_settings import BaseServerSettings +from bot_data.model.server_config import ServerConfig class BaseReactionHandler: def __init__( self, + config: ConfigurationABC, logger: MessageLogger, bot: DiscordBotServiceABC, servers: ServerRepositoryABC, users: UserRepositoryABC, - base_helper: BaseHelperABC, client_utils: ClientUtilsABC, db: DatabaseContextABC, ): + self._config = config self._logger = logger self._bot = bot self._servers = servers self._users = users - self._base_helper = base_helper self._client_utils = client_utils self._db = db @@ -70,7 +70,7 @@ class BaseReactionHandler: server = self._servers.get_server_by_discord_id(guild.id) user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) - settings: BaseServerSettings = self._base_helper.get_config(guild.id) + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{guild.id}") if r_type == "add": if self._client_utils.is_message_xp_count_by_hour_higher_that_max_message_count_per_hour( diff --git a/kdb-bot/src/modules/base/service/base_helper_service.py b/kdb-bot/src/modules/base/service/base_helper_service.py deleted file mode 100644 index 89c9d9c3..00000000 --- a/kdb-bot/src/modules/base/service/base_helper_service.py +++ /dev/null @@ -1,13 +0,0 @@ -from cpl_core.configuration import ConfigurationABC - -from modules.base.abc.base_helper_abc import BaseHelperABC -from modules.base.configuration.base_server_settings import BaseServerSettings - - -class BaseHelperService(BaseHelperABC): - def __init__(self, config: ConfigurationABC): - BaseHelperABC.__init__(self) - self._config = config - - def get_config(self, g_id: int) -> BaseServerSettings: - return self._config.get_configuration(f"BaseServerSettings_{g_id}") diff --git a/kdb-bot/src/modules/base/service/user_warnings_service.py b/kdb-bot/src/modules/base/service/user_warnings_service.py index a67d3258..dbf78bf9 100644 --- a/kdb-bot/src/modules/base/service/user_warnings_service.py +++ b/kdb-bot/src/modules/base/service/user_warnings_service.py @@ -11,8 +11,6 @@ from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC from bot_data.model.user import User from bot_data.model.user_warnings import UserWarnings -from modules.base.abc.base_helper_abc import BaseHelperABC -from modules.base.configuration.base_server_settings import BaseServerSettings from modules.level.service.level_service import LevelService from modules.permission.abc.permission_service_abc import PermissionServiceABC @@ -31,7 +29,6 @@ class UserWarningsService: message_service: MessageServiceABC, t: TranslatePipe, permissions: PermissionServiceABC, - base_helper: BaseHelperABC, ): self._logger = logger self._db = db @@ -44,11 +41,10 @@ class UserWarningsService: self._message_service = message_service self._t = t self._permissions = permissions - self._base_helper = base_helper async def notify_team(self, member: discord.Member, description: str, removed=False): try: - settings: BaseServerSettings = self._base_helper.get_config(member.guild.id) + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{member.guild.id}") channel = member.guild.get_channel(settings.team_channel_id) if removed: translation = self._t.transform("modules.base.warnings.team_removed").format( diff --git a/kdb-bot/src/modules/boot_log/boot_log_on_ready_event.py b/kdb-bot/src/modules/boot_log/boot_log_on_ready_event.py index 58c2b5c4..20810163 100644 --- a/kdb-bot/src/modules/boot_log/boot_log_on_ready_event.py +++ b/kdb-bot/src/modules/boot_log/boot_log_on_ready_event.py @@ -8,10 +8,7 @@ from cpl_translation import TranslatePipe from discord import guild from bot_core.abc.message_service_abc import MessageServiceABC -from bot_core.configuration.server_settings import ServerSettings -from modules.boot_log.configuration.boot_log_server_settings import ( - BootLogServerSettings, -) +from bot_data.model.server_config import ServerConfig class BootLogOnReadyEvent(OnReadyABC): @@ -58,19 +55,14 @@ class BootLogOnReadyEvent(OnReadyABC): g: guild = g self._logger.debug(__name__, f"Server detected: {g.id}") - server_settings: ServerSettings = self._config.get_configuration(f"ServerSettings_{g.id}") - if server_settings is None: - self._logger.error(__name__, f"BootLog settings for server {g.id} not found!") - return - - module_settings: BootLogServerSettings = self._config.get_configuration(f"BootLogServerSettings_{g.id}") - if module_settings is None: + server_config: ServerConfig = self._config.get_configuration(f"ServerConfig_{g.id}") + if server_config is None: self._logger.error(__name__, f"Config {type(self).__name__}_{g.id} not found!") return self._bot.loop.create_task( self._message_service.send_channel_message( - self._bot.get_channel(module_settings.login_message_channel_id), + self._bot.get_channel(server_config.login_message_channel_id), self._t.transform("modules.boot_log.login_message").format(init_time), ) ) diff --git a/kdb-bot/src/modules/boot_log/configuration/__init__.py b/kdb-bot/src/modules/boot_log/configuration/__init__.py deleted file mode 100644 index cdde1580..00000000 --- a/kdb-bot/src/modules/boot_log/configuration/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -bot Keksdose bot -~~~~~~~~~~~~~~~~~~~ - -Discord bot for the Keksdose discord Server - -:copyright: (c) 2022 - 2023 sh-edraft.de -:license: MIT, see LICENSE for more details. - -""" - -__title__ = "modules.boot_log.configuration" -__author__ = "Sven Heidemann" -__license__ = "MIT" -__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "1.0.7" - -from collections import namedtuple - - -# imports: - -VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="1", minor="0", micro="7") diff --git a/kdb-bot/src/modules/boot_log/configuration/boot_log_server_settings.py b/kdb-bot/src/modules/boot_log/configuration/boot_log_server_settings.py deleted file mode 100644 index 148609af..00000000 --- a/kdb-bot/src/modules/boot_log/configuration/boot_log_server_settings.py +++ /dev/null @@ -1,28 +0,0 @@ -import traceback - -from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console - - -class BootLogServerSettings(ConfigurationModelABC): - def __init__(self): - ConfigurationModelABC.__init__(self) - - self._id: int = 0 - self._login_message_channel_id: int = 0 - - @property - def id(self) -> int: - return self._id - - @property - def login_message_channel_id(self) -> int: - return self._login_message_channel_id - - def from_dict(self, settings: dict): - try: - self._id = int(settings["Id"]) - self._login_message_channel_id = int(settings["LoginMessageChannelId"]) - except Exception as e: - Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings") - Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") diff --git a/kdb-bot/src/modules/boot_log/configuration/boot_log_settings.py b/kdb-bot/src/modules/boot_log/configuration/boot_log_settings.py deleted file mode 100644 index d06ed5fb..00000000 --- a/kdb-bot/src/modules/boot_log/configuration/boot_log_settings.py +++ /dev/null @@ -1,33 +0,0 @@ -import traceback - -from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console -from cpl_query.extension import List - -from modules.boot_log.configuration.boot_log_server_settings import ( - BootLogServerSettings, -) - - -class BootLogSettings(ConfigurationModelABC): - def __init__(self): - ConfigurationModelABC.__init__(self) - - self._servers: List[BootLogServerSettings] = List() - - @property - def servers(self) -> List[BootLogServerSettings]: - return self._servers - - def from_dict(self, settings: dict): - try: - servers = List(BootLogServerSettings) - for s in settings: - st = BootLogServerSettings() - settings[s]["Id"] = s - st.from_dict(settings[s]) - servers.append(st) - self._servers = servers - except Exception as e: - Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings") - Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") diff --git a/kdb-bot/src/modules/config/__init__.py b/kdb-bot/src/modules/config/__init__.py new file mode 100644 index 00000000..425ab6c1 --- /dev/null +++ b/kdb-bot/src/modules/config/__init__.py @@ -0,0 +1 @@ +# imports diff --git a/kdb-bot/src/modules/config/config.json b/kdb-bot/src/modules/config/config.json new file mode 100644 index 00000000..de773221 --- /dev/null +++ b/kdb-bot/src/modules/config/config.json @@ -0,0 +1,46 @@ +{ + "ProjectSettings": { + "Name": "config", + "Version": { + "Major": "0", + "Minor": "0", + "Micro": "0" + }, + "Author": "", + "AuthorEmail": "", + "Description": "", + "LongDescription": "", + "URL": "", + "CopyrightDate": "", + "CopyrightName": "", + "LicenseName": "", + "LicenseDescription": "", + "Dependencies": [ + "cpl-core>=2023.4.0.post5" + ], + "DevDependencies": [ + "cpl-cli>=2023.4.0.post3" + ], + "PythonVersion": ">=3.10.4", + "PythonPath": { + "linux": "" + }, + "Classifiers": [] + }, + "BuildSettings": { + "ProjectType": "library", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "config.main", + "EntryPoint": "config", + "IncludePackageData": false, + "Included": [], + "Excluded": [ + "*/__pycache__", + "*/logs", + "*/tests" + ], + "PackageData": {}, + "ProjectReferences": [] + } +} \ No newline at end of file diff --git a/kdb-bot/src/modules/config/config_extension.py b/kdb-bot/src/modules/config/config_extension.py new file mode 100644 index 00000000..56f383e3 --- /dev/null +++ b/kdb-bot/src/modules/config/config_extension.py @@ -0,0 +1,24 @@ +from cpl_core.application.application_extension_abc import ApplicationExtensionABC +from cpl_core.configuration import ConfigurationABC +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_core.logging import LoggerABC + +from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum +from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings +from bot_data.abc.technician_config_repository_abc import TechnicianConfigRepositoryABC +from bot_data.model.technician_config import TechnicianConfig + + +class ConfigExtension(ApplicationExtensionABC): + def __init__(self): + pass + + async def run(self, config: ConfigurationABC, services: ServiceProviderABC): + feature_flags: FeatureFlagsSettings = config.get_configuration(FeatureFlagsSettings) + if not feature_flags.get_flag(FeatureFlagsEnum.config_module): + return + logger: LoggerABC = services.get_service(LoggerABC) + logger.debug(__name__, "Config extension started") + technician_config_repo: TechnicianConfigRepositoryABC = services.get_service(TechnicianConfigRepositoryABC) + technician_config = technician_config_repo.get_technician_config() + config.add_configuration(TechnicianConfig, technician_config) diff --git a/kdb-bot/src/modules/config/config_module.py b/kdb-bot/src/modules/config/config_module.py new file mode 100644 index 00000000..c55b62d1 --- /dev/null +++ b/kdb-bot/src/modules/config/config_module.py @@ -0,0 +1,20 @@ +from cpl_core.configuration import ConfigurationABC +from cpl_core.dependency_injection import ServiceCollectionABC +from cpl_core.environment import ApplicationEnvironmentABC +from cpl_discord.discord_event_types_enum import DiscordEventTypesEnum +from cpl_discord.service.discord_collection_abc import DiscordCollectionABC + +from bot_core.abc.module_abc import ModuleABC +from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum +from modules.config.events.config_on_ready_event import ConfigOnReadyEvent + + +class ConfigModule(ModuleABC): + def __init__(self, dc: DiscordCollectionABC): + ModuleABC.__init__(self, dc, FeatureFlagsEnum.config_module) + + def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC): + pass + + def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): + self._dc.add_event(DiscordEventTypesEnum.on_ready.value, ConfigOnReadyEvent) diff --git a/kdb-bot/src/modules/config/events/__init__.py b/kdb-bot/src/modules/config/events/__init__.py new file mode 100644 index 00000000..425ab6c1 --- /dev/null +++ b/kdb-bot/src/modules/config/events/__init__.py @@ -0,0 +1 @@ +# imports diff --git a/kdb-bot/src/modules/config/events/config_on_ready_event.py b/kdb-bot/src/modules/config/events/config_on_ready_event.py new file mode 100644 index 00000000..f9bf3012 --- /dev/null +++ b/kdb-bot/src/modules/config/events/config_on_ready_event.py @@ -0,0 +1,35 @@ +from cpl_core.configuration import ConfigurationABC +from cpl_core.logging import LoggerABC +from cpl_discord.container import Guild +from cpl_discord.events import OnReadyABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.abc.server_config_repository_abc import ServerConfigRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC + + +class ConfigOnReadyEvent(OnReadyABC): + def __init__( + self, + config: ConfigurationABC, + logger: LoggerABC, + bot: DiscordBotServiceABC, + servers: ServerRepositoryABC, + server_config_repo: ServerConfigRepositoryABC, + ): + OnReadyABC.__init__(self) + + self._config = config + self._logger = logger + self._bot = bot + self._servers = servers + self._server_config_repo = server_config_repo + + async def on_ready(self): + for guild in self._bot.guilds: + guild: Guild = guild + server = self._servers.get_server_by_discord_id(guild.id) + server_config = self._server_config_repo.get_server_config_by_server(server.id) + self._config.add_configuration( + f"{type(server_config).__name__}_{server_config.server.discord_id}", server_config + ) diff --git a/kdb-bot/src/modules/level/configuration/default_level_settings.py b/kdb-bot/src/modules/level/configuration/default_level_settings.py index fcce9e47..4e1c813f 100644 --- a/kdb-bot/src/modules/level/configuration/default_level_settings.py +++ b/kdb-bot/src/modules/level/configuration/default_level_settings.py @@ -1,18 +1,28 @@ -import traceback - from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console from cpl_query.extension import List from bot_data.model.level import Level class DefaultLevelSettings(ConfigurationModelABC): - def __init__(self): + def __init__(self, level_header: str = None, levels: list = None): ConfigurationModelABC.__init__(self) self._levels = List(Level) - self._level_header = "" + self._level_header = level_header + + if levels is None: + return + for level in levels: + self._levels.append( + Level( + level["Name"], + level["Color"], + int(level["MinXp"]), + int(level["Permissions"]), + None, + ) + ) @property def levels(self) -> List[Level]: @@ -21,20 +31,3 @@ class DefaultLevelSettings(ConfigurationModelABC): @property def level_header(self) -> str: return self._level_header - - def from_dict(self, settings: dict): - try: - self._level_header = settings["LevelHeader"] - for level in settings["Levels"]: - self._levels.append( - Level( - level["Name"], - level["Color"], - int(level["MinXp"]), - int(level["Permissions"]), - None, - ) - ) - except Exception as e: - Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings") - Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") diff --git a/kdb-bot/src/modules/level/service/level_service.py b/kdb-bot/src/modules/level/service/level_service.py index f4782592..7f710212 100644 --- a/kdb-bot/src/modules/level/service/level_service.py +++ b/kdb-bot/src/modules/level/service/level_service.py @@ -6,7 +6,6 @@ from cpl_discord.container import Guild, Role, Member from cpl_discord.service import DiscordBotServiceABC from cpl_translation import TranslatePipe -from bot_core.configuration.server_settings import ServerSettings from bot_core.service.message_service import MessageService from bot_data.model.level import Level from bot_data.model.user import User @@ -75,7 +74,7 @@ class LevelService: self._logger.error(__name__, f"Adding role {level_role.name} to {member.name} failed!", e) if notification_needed: - settings: ServerSettings = self._config.get_configuration(f"ServerSettings_{guild.id}") + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{guild.id}") await self._message_service.send_channel_message( self._bot.get_channel(settings.notification_chat_id), self._t.transform("modules.level.new_level_message").format(member.mention, level.name), diff --git a/kdb-bot/src/modules/permission/configuration/__init__.py b/kdb-bot/src/modules/permission/configuration/__init__.py deleted file mode 100644 index 60e3d7f5..00000000 --- a/kdb-bot/src/modules/permission/configuration/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -bot Keksdose bot -~~~~~~~~~~~~~~~~~~~ - -Discord bot for the Keksdose discord Server - -:copyright: (c) 2022 - 2023 sh-edraft.de -:license: MIT, see LICENSE for more details. - -""" - -__title__ = "modules.permission.configuration" -__author__ = "Sven Heidemann" -__license__ = "MIT" -__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "1.0.7" - -from collections import namedtuple - - -# imports - -VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="1", minor="0", micro="7") diff --git a/kdb-bot/src/modules/permission/configuration/permission_server_settings.py b/kdb-bot/src/modules/permission/configuration/permission_server_settings.py deleted file mode 100644 index 1ffdfdf7..00000000 --- a/kdb-bot/src/modules/permission/configuration/permission_server_settings.py +++ /dev/null @@ -1,37 +0,0 @@ -import traceback - -from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console - - -class PermissionServerSettings(ConfigurationModelABC): - def __init__(self): - ConfigurationModelABC.__init__(self) - - self._id: int = 0 - self._admin_roles: list[int] = [] - self._moderator_roles: list[int] = [] - - @property - def id(self) -> int: - return self._id - - @property - def admin_roles(self) -> list[int]: - return self._admin_roles - - @property - def moderator_roles(self) -> list[int]: - return self._moderator_roles - - def from_dict(self, settings: dict): - try: - self._id = int(settings["Id"]) - for index in settings["AdminRoleIds"]: - self._admin_roles.append(int(index)) - - for index in settings["ModeratorRoleIds"]: - self._moderator_roles.append(int(index)) - except Exception as e: - Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {self.__name__} settings") - Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") diff --git a/kdb-bot/src/modules/permission/configuration/permission_settings.py b/kdb-bot/src/modules/permission/configuration/permission_settings.py deleted file mode 100644 index 532c592a..00000000 --- a/kdb-bot/src/modules/permission/configuration/permission_settings.py +++ /dev/null @@ -1,33 +0,0 @@ -import traceback - -from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console -from cpl_query.extension import List - -from modules.permission.configuration.permission_server_settings import ( - PermissionServerSettings, -) - - -class PermissionSettings(ConfigurationModelABC): - def __init__(self): - ConfigurationModelABC.__init__(self) - - self._servers: List[PermissionServerSettings] = List() - - @property - def servers(self) -> List[PermissionServerSettings]: - return self._servers - - def from_dict(self, settings: dict): - try: - servers = List(PermissionServerSettings) - for s in settings: - st = PermissionServerSettings() - settings[s]["Id"] = s - st.from_dict(settings[s]) - servers.append(st) - self._servers = servers - except Exception as e: - Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings") - Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") diff --git a/kdb-bot/src/modules/permission/service/permission_service.py b/kdb-bot/src/modules/permission/service/permission_service.py index c13f517c..f94a1ff1 100644 --- a/kdb-bot/src/modules/permission/service/permission_service.py +++ b/kdb-bot/src/modules/permission/service/permission_service.py @@ -3,25 +3,25 @@ from cpl_core.configuration import ConfigurationABC from cpl_core.logging import LoggerABC from cpl_discord.service import DiscordBotServiceABC -from bot_core.configuration.bot_settings import BotSettings +from bot_data.model.server_config import ServerConfig +from bot_data.model.team_member_type_enum import TeamMemberTypeEnum +from bot_data.model.technician_config import TechnicianConfig from modules.permission.abc.permission_service_abc import PermissionServiceABC -from modules.permission.configuration.permission_server_settings import ( - PermissionServerSettings, -) class PermissionService(PermissionServiceABC): def __init__( self, + technician_settings: TechnicianConfig, logger: LoggerABC, bot: DiscordBotServiceABC, config: ConfigurationABC, - bot_settings: BotSettings, ): PermissionServiceABC.__init__(self) self._logger = logger self._bot = bot self._config = config + self._technician_settings = technician_settings self._admin_role_ids: dict[int, list[int]] = {} self._admin_roles: dict[int, list[discord.Role]] = {} @@ -31,7 +31,7 @@ class PermissionService(PermissionServiceABC): self._moderator_roles: dict[int, list[discord.Role]] = {} self._moderators: dict[int, list[discord.Member]] = {} - self._technician_ids: list[int] = bot_settings.technicians + self._technician_ids: list[int] = technician_settings.technician_ids.to_list() self._technicians: list[discord.Member] = [] def on_ready(self): @@ -45,13 +45,21 @@ class PermissionService(PermissionServiceABC): continue self._technicians.append(technician) - settings: PermissionServerSettings = self._config.get_configuration(f"PermissionServerSettings_{guild.id}") + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{guild.id}") if settings is None: - self._logger.error(__name__, "Permission settings not found") + self._logger.error(__name__, "Server settings not found") return - self._admin_role_ids[guild.id] = settings.admin_roles - self._moderator_role_ids[guild.id] = settings.moderator_roles + self._admin_role_ids[guild.id] = ( + settings.team_role_ids.where(lambda x: x.team_member_type == TeamMemberTypeEnum.admin) + .select(lambda x: x.role_id) + .to_list() + ) + self._moderator_role_ids[guild.id] = ( + settings.team_role_ids.where(lambda x: x.team_member_type == TeamMemberTypeEnum.moderator) + .select(lambda x: x.role_id) + .to_list() + ) admin_roles = [] admins = [] diff --git a/kdb-bot/src/modules/technician/command/restart_command.py b/kdb-bot/src/modules/technician/command/restart_command.py index 302ba7e9..62029cec 100644 --- a/kdb-bot/src/modules/technician/command/restart_command.py +++ b/kdb-bot/src/modules/technician/command/restart_command.py @@ -9,7 +9,6 @@ from discord.ext.commands import Context from bot_core.abc.client_utils_abc import ClientUtilsABC from bot_core.abc.message_service_abc import MessageServiceABC -from bot_core.configuration.bot_settings import BotSettings from bot_core.helper.command_checks import CommandChecks from bot_core.logging.command_logger import CommandLogger from modules.permission.abc.permission_service_abc import PermissionServiceABC @@ -25,7 +24,6 @@ class RestartCommand(DiscordCommandABC): client_utils: ClientUtilsABC, translate: TranslatePipe, permissions: PermissionServiceABC, - settings: BotSettings, ): DiscordCommandABC.__init__(self) @@ -36,7 +34,6 @@ class RestartCommand(DiscordCommandABC): self._client_utils = client_utils self._t = translate self._permissions = permissions - self._settings = settings self._logger.trace(__name__, f"Loaded command service: {type(self).__name__}") diff --git a/kdb-bot/src/modules/technician/command/shutdown_command.py b/kdb-bot/src/modules/technician/command/shutdown_command.py index 6ba52651..44e01464 100644 --- a/kdb-bot/src/modules/technician/command/shutdown_command.py +++ b/kdb-bot/src/modules/technician/command/shutdown_command.py @@ -1,6 +1,5 @@ import asyncio -import discord from cpl_core.configuration import ConfigurationABC from cpl_discord.command import DiscordCommandABC from cpl_discord.service import DiscordBotServiceABC @@ -10,9 +9,9 @@ from discord.ext.commands import Context from bot_core.abc.client_utils_abc import ClientUtilsABC from bot_core.abc.message_service_abc import MessageServiceABC -from bot_core.configuration.bot_settings import BotSettings from bot_core.helper.command_checks import CommandChecks from bot_core.logging.command_logger import CommandLogger +from bot_data.model.technician_config import TechnicianConfig from modules.permission.abc.permission_service_abc import PermissionServiceABC @@ -26,7 +25,7 @@ class ShutdownCommand(DiscordCommandABC): client_utils: ClientUtilsABC, translate: TranslatePipe, permissions: PermissionServiceABC, - settings: BotSettings, + settings: TechnicianConfig, ): DiscordCommandABC.__init__(self) diff --git a/kdb-bot/src/modules/technician/technician_module.py b/kdb-bot/src/modules/technician/technician_module.py index 9aa5089c..57282ebc 100644 --- a/kdb-bot/src/modules/technician/technician_module.py +++ b/kdb-bot/src/modules/technician/technician_module.py @@ -6,8 +6,6 @@ from cpl_discord.service.discord_collection_abc import DiscordCollectionABC from bot_core.abc.module_abc import ModuleABC from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from bot_data.abc.data_seeder_abc import DataSeederABC -from modules.base.abc.base_helper_abc import BaseHelperABC -from modules.base.service.base_helper_service import BaseHelperService from modules.technician.api_key_seeder import ApiKeySeeder from modules.technician.command.api_key_group import ApiKeyGroup from modules.technician.command.log_command import LogCommand @@ -24,7 +22,6 @@ class TechnicianModule(ModuleABC): def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): services.add_transient(DataSeederABC, ApiKeySeeder) - services.add_transient(BaseHelperABC, BaseHelperService) # commands self._dc.add_command(RestartCommand) self._dc.add_command(ShutdownCommand) diff --git a/kdb-web/package-lock.json b/kdb-web/package-lock.json index 9c7b31b2..9281a434 100644 --- a/kdb-web/package-lock.json +++ b/kdb-web/package-lock.json @@ -1,12 +1,12 @@ { "name": "kdb-web", - "version": "1.0.dev251", + "version": "1.0.dev127_config_in_wi", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "kdb-web", - "version": "1.0.dev251", + "version": "1.0.dev127_config_in_wi", "dependencies": { "@angular/animations": "^15.1.4", "@angular/common": "^15.1.4", @@ -21,6 +21,7 @@ "@ngx-translate/core": "^14.0.0", "@ngx-translate/http-loader": "^7.0.0", "@types/socket.io-client": "^3.0.0", + "primeflex": "^3.3.1", "primeicons": "^6.0.1", "primeng": "^15.2.0", "rxjs": "~7.5.0", @@ -9302,6 +9303,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/primeflex": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/primeflex/-/primeflex-3.3.1.tgz", + "integrity": "sha512-zaOq3YvcOYytbAmKv3zYc+0VNS9Wg5d37dfxZnveKBFPr7vEIwfV5ydrpiouTft8MVW6qNjfkaQphHSnvgQbpQ==" + }, "node_modules/primeicons": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/primeicons/-/primeicons-6.0.1.tgz", diff --git a/kdb-web/src/app/models/config/server-config.model.ts b/kdb-web/src/app/models/config/server-config.model.ts new file mode 100644 index 00000000..b55c4136 --- /dev/null +++ b/kdb-web/src/app/models/config/server-config.model.ts @@ -0,0 +1,21 @@ +import { DataWithHistory } from "../data/data.model"; + +export interface ServerConfig extends DataWithHistory { + id?: number; + messageDeleteTimer?: number; + notificationChatId?: string; + maxVoiceStateHours?: number; + xpPerMessage?: number; + xpPerReaction?: number; + maxMessageXpPerHour?: number; + xpPerOntimeHour?: number; + xpPerEventParticipation?: number; + xpPerAchievement?: number; + afkCommandChannelId?: string; + helpVoiceChannelId?: string; + teamChannelId?: string; + loginMessageChannelId?: string; + afkChannelIds: string[]; + moderatorRoleIds: string[]; + adminRoleIds: string[]; +} diff --git a/kdb-web/src/app/models/config/technician-config.model.ts b/kdb-web/src/app/models/config/technician-config.model.ts new file mode 100644 index 00000000..6e1430f0 --- /dev/null +++ b/kdb-web/src/app/models/config/technician-config.model.ts @@ -0,0 +1,11 @@ +import { DataWithHistory } from "../data/data.model"; + +export interface TechnicianConfig extends DataWithHistory { + id?: number; + helpCommandReferenceUrl?: string; + waitForRestart?: number; + waitForShutdown?: number; + cacheMaxMessages?: number; + pingURLs: string[]; + technicianIds: string[]; +} diff --git a/kdb-web/src/app/models/graphql/mutations.model.ts b/kdb-web/src/app/models/graphql/mutations.model.ts index ac4448d0..7905eff4 100644 --- a/kdb-web/src/app/models/graphql/mutations.model.ts +++ b/kdb-web/src/app/models/graphql/mutations.model.ts @@ -165,4 +165,94 @@ export class Mutations { } } `; + + static updateTechnicianConfig = ` + mutation updateTechnicianConfig($id: ID, $helpCommandReferenceUrl: String, $waitForRestart: Int, $waitForShutdown: Int, $cacheMaxMessages: Int, $pingURLs: [String], $technicianIds: [String]) { + technicianConfig { + updateTechnicianConfig(input: { + id: $id, + helpCommandReferenceUrl: $helpCommandReferenceUrl, + waitForRestart: $waitForRestart, + waitForShutdown: $waitForShutdown, + cacheMaxMessages: $cacheMaxMessages, + pingURLs: $pingURLs, + technicianIds: $technicianIds + }) { + id + helpCommandReferenceUrl + waitForRestart + waitForShutdown + cacheMaxMessages + pingURLs + technicianIds + } + } + } + `; + + static updateServerConfig = ` + mutation updateServerConfig( + $id: ID, + $messageDeleteTimer: Int, + $notificationChatId: String, + $maxVoiceStateHours: Int, + $xpPerMessage: Int, + $xpPerReaction: Int, + $maxMessageXpPerHour: Int, + $xpPerOntimeHour: Int, + $xpPerEventParticipation: Int, + $xpPerAchievement: Int, + $afkCommandChannelId: String, + $helpVoiceChannelId: String, + $teamChannelId: String, + $loginMessageChannelId: String, + $afkChannelIds: [String], + $moderatorRoleIds: [String], + $adminRoleIds: [String] + ) { + serverConfig { + updateServerConfig(input: { + id: $id, + messageDeleteTimer: $messageDeleteTimer + notificationChatId: $notificationChatId + maxVoiceStateHours: $maxVoiceStateHours + xpPerMessage: $xpPerMessage + xpPerReaction: $xpPerReaction + maxMessageXpPerHour: $maxMessageXpPerHour + xpPerOntimeHour: $xpPerOntimeHour + xpPerEventParticipation: $xpPerEventParticipation + xpPerAchievement: $xpPerAchievement + afkCommandChannelId: $afkCommandChannelId + helpVoiceChannelId: $helpVoiceChannelId + teamChannelId: $teamChannelId + loginMessageChannelId: $loginMessageChannelId + afkChannelIds: $afkChannelIds + moderatorRoleIds: $moderatorRoleIds + adminRoleIds: $adminRoleIds + }) { + id + messageDeleteTimer + notificationChatId + maxVoiceStateHours + xpPerMessage + xpPerReaction + maxMessageXpPerHour + xpPerOntimeHour + xpPerEventParticipation + xpPerAchievement + afkCommandChannelId + helpVoiceChannelId + teamChannelId + loginMessageChannelId + afkChannelIds + moderatorRoleIds + adminRoleIds + + server { + id + } + } + } + } + `; } diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts index 6dc78904..55998599 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -54,7 +54,7 @@ export class Queries { } } } - ` + `; static levelQuery = ` query LevelsList($serverId: ID, $filter: LevelFilter, $page: Page, $sort: Sort) { @@ -344,4 +344,52 @@ export class Queries { } } `; + + static technicianConfigQuery = ` + query technicianConfigQuery { + technicianConfig { + id + helpCommandReferenceUrl + waitForRestart + waitForShutdown + cacheMaxMessages + pingURLs + technicianIds + + createdAt + modifiedAt + } + } + `; + + static serverConfigQuery = ` + query serverConfigQuery($serverId: ID) { + servers(filter: { id: $serverId }) { + name + config { + id + messageDeleteTimer + notificationChatId + maxVoiceStateHours + xpPerMessage + xpPerReaction + maxMessageXpPerHour + xpPerOntimeHour + xpPerEventParticipation + xpPerAchievement + afkCommandChannelId + helpVoiceChannelId + teamChannelId + loginMessageChannelId + afkChannelIds + moderatorRoleIds + adminRoleIds + + server { + id + } + } + } + } + `; } diff --git a/kdb-web/src/app/models/graphql/query.model.ts b/kdb-web/src/app/models/graphql/query.model.ts index 92c54ae7..42eeb69d 100644 --- a/kdb-web/src/app/models/graphql/query.model.ts +++ b/kdb-web/src/app/models/graphql/query.model.ts @@ -4,12 +4,22 @@ import { AutoRole, AutoRoleRule } from "../data/auto_role.model"; import { Guild } from "../data/discord.model"; import { Level } from "../data/level.model"; import { Achievement, AchievementAttribute } from "../data/achievement.model"; +import { TechnicianConfig } from "../config/technician-config.model"; +import { ServerConfig } from "../config/server-config.model"; export interface Query { serverCount: number; servers: Server[]; } +export interface TechnicianConfigQuery { + technicianConfig: TechnicianConfig; +} + +export interface ServerConfigQuery { + config: ServerConfig; +} + export interface SingleDiscordQuery { guilds: Guild[]; } diff --git a/kdb-web/src/app/models/graphql/result.model.ts b/kdb-web/src/app/models/graphql/result.model.ts index d77c2cdc..573f98ce 100644 --- a/kdb-web/src/app/models/graphql/result.model.ts +++ b/kdb-web/src/app/models/graphql/result.model.ts @@ -3,6 +3,8 @@ import { AutoRole, AutoRoleRule } from "../data/auto_role.model"; import { Level } from "../data/level.model"; import { Server } from "../data/server.model"; import { Achievement } from "../data/achievement.model"; +import { TechnicianConfig } from "../config/technician-config.model"; +import { ServerConfig } from "../config/server-config.model"; export interface GraphQLResult { data: { @@ -47,6 +49,18 @@ export interface LevelMutationResult { }; } +export interface TechnicianConfigMutationResult { + technicianConfig: { + updateTechnicianConfig?: TechnicianConfig + }; +} + +export interface ServerConfigMutationResult { + serverConfig: { + updateServerConfig?: ServerConfig + }; +} + export interface AchievementMutationResult { achievement: { createAchievement?: Achievement diff --git a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html index 3c78d1a6..b7e68a1b 100644 --- a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html +++ b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html @@ -1,125 +1,172 @@

- {{'admin.settings.header' | translate}} + {{'admin.settings.header' | translate}}

-
-

- {{'admin.settings.website.header' | translate}} -

+
+

+ {{'admin.settings.website.header' | translate}} +

+
+ +
+
+
+
{{'admin.settings.website.frontend_version' | translate}}:
+
{{data.webVersion}}
+
-
-
-
-
{{'admin.settings.website.frontend_version' | translate}}:
-
{{data.webVersion}}
-
-
- -
-
-
{{'admin.settings.website.backend_version' | translate}}:
-
{{data.apiVersion}}
-
-
- -
-
-
{{'admin.settings.website.config_path' | translate}}:
-
{{data.configPath}}
-
-
- -
-
-
{{'admin.settings.website.frontend_base_url' | translate}}:
-
{{data.webBaseURL}}
-
-
- -
-
-
{{'admin.settings.website.backend_base_url' | translate}}:
-
{{data.apiBaseURL}}
-
-
- -
- -
-
-
{{'admin.settings.website.token_expire_time' | translate}}:
-
{{data.tokenExpireTime}} {{'general.minutes' | translate}}
-
-
- -
-
-
{{'admin.settings.website.refresh_token_expire_time' | translate}}:
-
{{data.refreshTokenExpireTime}} {{'general.days' | translate}}
-
-
+
+
+
{{'admin.settings.website.backend_version' | translate}}:
+
{{data.apiVersion}}
+
+ +
+
+
{{'admin.settings.website.config_path' | translate}}:
+
{{data.configPath}}
+
+
+ +
+
+
{{'admin.settings.website.frontend_base_url' | translate}}:
+
{{data.webBaseURL}}
+
+
+ +
+
+
{{'admin.settings.website.backend_base_url' | translate}}:
+
{{data.apiBaseURL}}
+
+
+ +
+ +
+
+
{{'admin.settings.website.token_expire_time' | translate}}:
+
{{data.tokenExpireTime}} {{'general.minutes' | translate}}
+
+
+ +
+
+
{{'admin.settings.website.refresh_token_expire_time' | translate}}:
+
{{data.refreshTokenExpireTime}} {{'general.days' | translate}}
+
+
+
-
-

- {{'admin.settings.email.header' | translate}} -

+
+

+ {{'admin.settings.email.header' | translate}} +

+
+ +
+
+
+
{{'admin.settings.email.user' | translate}}:
+
{{data.mailUser}}
+
-
-
-
-
{{'admin.settings.email.user' | translate}}:
-
{{data.mailUser}}
-
-
- -
-
-
{{'admin.settings.email.host' | translate}}:
-
{{data.mailHost}}
-
-
- -
-
-
{{'admin.settings.email.port' | translate}}:
-
{{data.mailPort}}
-
-
- -
-
-
{{'admin.settings.email.transceiver' | translate}}:
-
{{data.mailTransceiver}}
-
-
- -
-
-
{{'admin.settings.email.email_address' | translate}}:
-
{{data.mailTransceiverAddress}}
-
-
- -
-
-
-
- -
-
- -
- -
-
-
+
+
+
{{'admin.settings.email.host' | translate}}:
+
{{data.mailHost}}
+
+ +
+
+
{{'admin.settings.email.port' | translate}}:
+
{{data.mailPort}}
+
+
+ +
+
+
{{'admin.settings.email.transceiver' | translate}}:
+
{{data.mailTransceiver}}
+
+
+ +
+
+
{{'admin.settings.email.email_address' | translate}}:
+
{{data.mailTransceiverAddress}}
+
+
+ +
+
+
+
+ +
+
+ +
+ +
+
+
+
+
+ +
+
+

+ {{'admin.settings.bot.header' | translate}} +

+
+ +
+
+
+
{{'admin.settings.bot.help_url' | translate}}:
+ +
+
+ +
+
+
{{'admin.settings.bot.wait_for_restart' | translate}}:
+ +
+
+ +
+
+
{{'admin.settings.bot.wait_for_shutdown' | translate}}:
+ +
+
+ +
+
+
{{'admin.settings.bot.cache_max_messages' | translate}}:
+ +
+
+ +
+ + + +
+ +
+
diff --git a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.ts b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.ts index 0f88f42e..c4b691a7 100644 --- a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.ts +++ b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.ts @@ -9,65 +9,90 @@ import { GuiService } from "src/app/services/gui/gui.service"; import { SettingsService } from "src/app/services/settings/settings.service"; import { SpinnerService } from "src/app/services/spinner/spinner.service"; import { ToastService } from "src/app/services/toast/toast.service"; -import { throwError } from "rxjs"; +import { forkJoin, throwError } from "rxjs"; +import { TechnicianConfig } from "../../../../../models/config/technician-config.model"; +import { TechnicianConfigQuery } from "../../../../../models/graphql/query.model"; +import { Queries } from "../../../../../models/graphql/queries.model"; +import { DataService } from "../../../../../services/data/data.service"; +import { TechnicianConfigMutationResult } from "../../../../../models/graphql/result.model"; +import { Mutations } from "../../../../../models/graphql/mutations.model"; +import { AuthService } from "../../../../../services/auth/auth.service"; + @Component({ - selector: 'app-settings', - templateUrl: './settings.component.html', - styleUrls: ['./settings.component.scss'] + selector: "app-settings", + templateUrl: "./settings.component.html", + styleUrls: ["./settings.component.scss"] }) export class SettingsComponent implements OnInit { testMailForm!: FormGroup; data: SettingsDTO = { - webVersion: '', - apiVersion: '', - configPath: '', - webBaseURL: '', - apiBaseURL: '', + webVersion: "", + apiVersion: "", + configPath: "", + webBaseURL: "", + apiBaseURL: "", tokenExpireTime: 0, refreshTokenExpireTime: 0, - mailUser: '', + mailUser: "", mailPort: 0, - mailHost: '', - mailTransceiver: '', - mailTransceiverAddress: '', + mailHost: "", + mailTransceiver: "", + mailTransceiverAddress: "" + }; + + config: TechnicianConfig = { + helpCommandReferenceUrl: "", + waitForRestart: 0, + waitForShutdown: 0, + cacheMaxMessages: 0, + pingURLs: [], + technicianIds: [] }; constructor( + private dataService: DataService, private settingsService: SettingsService, private spinnerService: SpinnerService, private guiService: GuiService, private formBuilder: FormBuilder, private toastService: ToastService, - private translate: TranslateService - ) { } + private translate: TranslateService, + private authService: AuthService, + private spinner: SpinnerService + ) { + } ngOnInit(): void { this.spinnerService.showSpinner(); this.initForms(); - this.guiService.getSettings() - .pipe(catchError(error => { + forkJoin([ + this.guiService.getSettings().pipe(catchError(error => { this.spinnerService.hideSpinner(); return throwError(() => error); - })) - .subscribe(settings => { - this.spinnerService.hideSpinner(); - this.data = settings; - this.data.webVersion = this.settingsService.getWebVersion()?.getVersionString() ?? '0.0.0'; - this.data.apiBaseURL = this.settingsService.getApiURL(); - if (!this.data.apiBaseURL.endsWith('/')) { - this.data.apiBaseURL += '/'; - } - }); + })), + this.dataService.query(Queries.technicianConfigQuery) + ]).subscribe(data => { + this.data = data[0]; + this.data.webVersion = this.settingsService.getWebVersion()?.getVersionString() ?? "0.0.0"; + this.data.apiBaseURL = this.settingsService.getApiURL(); + if (!this.data.apiBaseURL.endsWith("/")) { + this.data.apiBaseURL += "/"; + } + + this.config = data[1].technicianConfig; + this.initForms(); + this.spinnerService.hideSpinner(); + }); } initForms(): void { this.testMailForm = this.formBuilder.group({ - mail: [null, [Validators.required, Validators.email]], + mail: [null, [Validators.required, Validators.email]] }); } @@ -82,27 +107,27 @@ export class SettingsComponent implements OnInit { this.guiService.sendTestMail(mail) .pipe(catchError(error => { - let header = this.translate.instant('admin.settings.message.error'); - let message = this.translate.instant('admin.settings.message.could_not_send_mail'); + let header = this.translate.instant("admin.settings.message.error"); + let message = this.translate.instant("admin.settings.message.could_not_send_mail"); if (error.error !== null) { const err: ErrorDTO = error.error; if (err.errorCode === ServiceErrorCode.ConnectionFailed) { - header = this.translate.instant('admin.settings.message.connection_failed'); - message = this.translate.instant('admin.settings.message.connection_to_mail_failed'); + header = this.translate.instant("admin.settings.message.connection_failed"); + message = this.translate.instant("admin.settings.message.connection_to_mail_failed"); error.error = null; } if (err.errorCode === ServiceErrorCode.InvalidUser) { - header = this.translate.instant('admin.settings.message.connection_failed'); - message = this.translate.instant('admin.settings.message.mail_login_failed'); + header = this.translate.instant("admin.settings.message.connection_failed"); + message = this.translate.instant("admin.settings.message.mail_login_failed"); error.error = null; } if (err.errorCode === ServiceErrorCode.MailError) { - header = this.translate.instant('admin.settings.message.send_failed'); - message = this.translate.instant('admin.settings.message.test_mail_not_send'); + header = this.translate.instant("admin.settings.message.send_failed"); + message = this.translate.instant("admin.settings.message.test_mail_not_send"); error.error = null; } } @@ -113,9 +138,29 @@ export class SettingsComponent implements OnInit { })) .subscribe(res => { this.spinnerService.hideSpinner(); - this.toastService.success(this.translate.instant('admin.settings.message.success'), this.translate.instant('admin.settings.message.send_mail')); + this.toastService.success(this.translate.instant("admin.settings.message.success"), this.translate.instant("admin.settings.message.send_mail")); this.testMailForm.reset(); }); } + saveTechnicianConfig() { + this.spinner.showSpinner(); + this.dataService.mutation(Mutations.updateTechnicianConfig, { + helpCommandReferenceUrl: this.config.helpCommandReferenceUrl, + waitForRestart: this.config.waitForRestart, + waitForShutdown: this.config.waitForShutdown, + cacheMaxMessages: this.config.cacheMaxMessages, + pingURLs: this.config.pingURLs, + technicianIds: this.config.technicianIds + } + ).pipe(catchError(err => { + this.spinner.hideSpinner(); + return throwError(err); + })).subscribe(result => { + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("admin.settings.message.technician_config_create"), this.translate.instant("admin.settings.message.technician_config_create_d")); + }); + } + + } diff --git a/kdb-web/src/app/modules/shared/components/config-list/config-list.component.html b/kdb-web/src/app/modules/shared/components/config-list/config-list.component.html new file mode 100644 index 00000000..4e3ea7d2 --- /dev/null +++ b/kdb-web/src/app/modules/shared/components/config-list/config-list.component.html @@ -0,0 +1,45 @@ +
+
+
+ {{translationKey | translate}}: +
+
+ + +
+
+ +
+
+
+ + + + + + + + + {{value.value}} + + + + +
+ + + + + +
+ + +
+
+
+
+
+
diff --git a/kdb-web/src/app/modules/shared/components/config-list/config-list.component.scss b/kdb-web/src/app/modules/shared/components/config-list/config-list.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/shared/components/config-list/config-list.component.spec.ts b/kdb-web/src/app/modules/shared/components/config-list/config-list.component.spec.ts new file mode 100644 index 00000000..b571849c --- /dev/null +++ b/kdb-web/src/app/modules/shared/components/config-list/config-list.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConfigListComponent } from './config-list.component'; + +describe('ConfigListComponent', () => { + let component: ConfigListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ConfigListComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ConfigListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/shared/components/config-list/config-list.component.ts b/kdb-web/src/app/modules/shared/components/config-list/config-list.component.ts new file mode 100644 index 00000000..7fc92215 --- /dev/null +++ b/kdb-web/src/app/modules/shared/components/config-list/config-list.component.ts @@ -0,0 +1,72 @@ +import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core"; +import { Table } from "primeng/table"; + +@Component({ + selector: "app-config-list", + templateUrl: "./config-list.component.html", + styleUrls: ["./config-list.component.scss"] +}) +export class ConfigListComponent { + internal_data: any[] = []; + + @Input() translationKey: string = ""; + + @Input() + set data(val: any[]) { + this.dataChange.emit(val); + let id = 0; + this.internal_data = val.map(value => { + value = { id: id, value: value }; + id++; + return value; + }); + } + + get data() { + return this.getData(); + } + + @Output() dataChange: EventEmitter = new EventEmitter(); + clonedData: { [s: number]: any } = {}; + + private getData(): any[] { + return this.internal_data.map(value => { + return value.value; + }); + } + + addNew(table: Table) { + const id = Math.max.apply(Math, this.internal_data.map(value => { + return value.id ?? 0; + })) + 1; + const newItem = { id: id, value: "" }; + this.internal_data.push(newItem); + + table.initRowEdit(newItem); + const index = this.internal_data.findIndex(l => l.id == newItem.id); + this.editInit(newItem, index); + } + + editInit(value: any, index: number) { + this.clonedData[index] = { ...value }; + } + + delete(index: number) { + this.internal_data.splice(index, 1); + this.dataChange.emit(this.getData()); + } + + editSave(value: any, index: number) { + if (!value.value || this.internal_data[index] == this.clonedData[index]) { + return; + } + + delete this.clonedData[index]; + this.dataChange.emit(this.getData()); + } + + editCancel(index: number) { + this.internal_data[index] = this.clonedData[index]; + delete this.clonedData[index]; + } +} diff --git a/kdb-web/src/app/modules/shared/shared.module.ts b/kdb-web/src/app/modules/shared/shared.module.ts index e2d14884..b92aa75b 100644 --- a/kdb-web/src/app/modules/shared/shared.module.ts +++ b/kdb-web/src/app/modules/shared/shared.module.ts @@ -24,6 +24,8 @@ import { InputNumberModule } from "primeng/inputnumber"; import { ImageModule } from "primeng/image"; import { SidebarModule } from "primeng/sidebar"; import { HistoryBtnComponent } from './components/history-btn/history-btn.component'; +import { DataViewModule, DataViewLayoutOptions } from 'primeng/dataview'; +import { ConfigListComponent } from './components/config-list/config-list.component'; @NgModule({ @@ -32,6 +34,7 @@ import { HistoryBtnComponent } from './components/history-btn/history-btn.compon IpAddressPipe, BoolPipe, HistoryBtnComponent, + ConfigListComponent, ], imports: [ CommonModule, @@ -56,33 +59,37 @@ import { HistoryBtnComponent } from './components/history-btn/history-btn.compon InputNumberModule, ImageModule, SidebarModule, + DataViewModule, ], - exports: [ - ButtonModule, - PasswordModule, - MenuModule, - DialogModule, - ProgressSpinnerModule, - HttpClientModule, - FormsModule, - ReactiveFormsModule, - ToastModule, - ConfirmDialogModule, - TableModule, - InputTextModule, - CheckboxModule, - DropdownModule, - TranslateModule, - DynamicDialogModule, - PanelMenuModule, - PanelModule, - AuthRolePipe, - IpAddressPipe, - BoolPipe, - InputNumberModule, - ImageModule, - SidebarModule, - HistoryBtnComponent - ] + exports: [ + ButtonModule, + PasswordModule, + MenuModule, + DialogModule, + ProgressSpinnerModule, + HttpClientModule, + FormsModule, + ReactiveFormsModule, + ToastModule, + ConfirmDialogModule, + TableModule, + InputTextModule, + CheckboxModule, + DropdownModule, + TranslateModule, + DynamicDialogModule, + PanelMenuModule, + PanelModule, + AuthRolePipe, + IpAddressPipe, + BoolPipe, + InputNumberModule, + ImageModule, + SidebarModule, + HistoryBtnComponent, + DataViewModule, + DataViewLayoutOptions, + ConfigListComponent + ] }) export class SharedModule { } diff --git a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.ts b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.ts index 114d1d8a..6a65d21c 100644 --- a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.ts +++ b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.ts @@ -236,7 +236,6 @@ export class AchievementComponent implements OnInit, OnDestroy { ).pipe(catchError(err => { this.isEditingNew = false; this.spinner.hideSpinner(); - this.toastService.error(this.translate.instant("view.server.achievements.message.achievement_create_failed"), this.translate.instant("view.server.achievements.message.achievement_create_failed_d")); return throwError(err); })).subscribe(result => { this.isEditingNew = false; @@ -258,7 +257,6 @@ export class AchievementComponent implements OnInit, OnDestroy { } ).pipe(catchError(err => { this.spinner.hideSpinner(); - this.toastService.error(this.translate.instant("view.server.achievements.message.achievement_update_failed"), this.translate.instant("view.server.achievements.message.achievement_update_failed_d", { name: newAchievement.name })); return throwError(err); })).subscribe(_ => { this.spinner.hideSpinner(); @@ -290,7 +288,6 @@ export class AchievementComponent implements OnInit, OnDestroy { } ).pipe(catchError(err => { this.spinner.hideSpinner(); - this.toastService.error(this.translate.instant("view.server.achievements.message.achievement_delete_failed"), this.translate.instant("view.server.achievements.message.achievement_delete_failed_d", { name: achievement.name })); return throwError(err); })).subscribe(l => { this.spinner.hideSpinner(); diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts index 5fab0523..25257687 100644 --- a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts +++ b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts @@ -222,7 +222,6 @@ export class AutoRolesRulesComponent implements OnInit, OnDestroy { ).pipe(catchError(err => { this.isEditingNew = false; this.spinner.hideSpinner(); - this.toastService.error(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_create_failed"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_create_failed_d")); return throwError(err); })).subscribe(result => { this.isEditingNew = false; @@ -241,7 +240,6 @@ export class AutoRolesRulesComponent implements OnInit, OnDestroy { } ).pipe(catchError(err => { this.spinner.hideSpinner(); - this.toastService.error(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_update_failed"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_update_failed_d")); return throwError(err); })).subscribe(result => { this.spinner.hideSpinner(); @@ -272,7 +270,6 @@ export class AutoRolesRulesComponent implements OnInit, OnDestroy { } ).pipe(catchError(err => { this.spinner.hideSpinner(); - this.toastService.error(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_delete_failed"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_delete_failed_d", { id: autoRoleRule.id })); return throwError(err); })).subscribe(_ => { this.spinner.hideSpinner(); diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts index 77f249ad..876f3b4a 100644 --- a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts +++ b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts @@ -208,7 +208,6 @@ export class AutoRolesComponent implements OnInit, OnDestroy { ).pipe(catchError(err => { this.isEditingNew = false; this.spinner.hideSpinner(); - this.toastService.error(this.translate.instant("view.server.auto_roles.message.auto_role_create_failed"), this.translate.instant("view.server.auto_roles.message.auto_role_create_failed_d")); return throwError(err); })).subscribe(result => { this.isEditingNew = false; @@ -240,7 +239,6 @@ export class AutoRolesComponent implements OnInit, OnDestroy { } ).pipe(catchError(err => { this.spinner.hideSpinner(); - this.toastService.error(this.translate.instant("view.server.auto_roles.message.auto_role_delete_failed"), this.translate.instant("view.server.auto_roles.message.auto_role_delete_failed_d", { id: autoRole.id })); return throwError(err); })).subscribe(_ => { this.spinner.hideSpinner(); diff --git a/kdb-web/src/app/modules/view/server/config/components/config/config.component.html b/kdb-web/src/app/modules/view/server/config/components/config/config.component.html new file mode 100644 index 00000000..9f7701c1 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/config/components/config/config.component.html @@ -0,0 +1,123 @@ +

+ {{'view.server.config.header' | translate}} +

+ +
+
+

+ {{'view.server.config.bot.header' | translate}} +

+
+ +
+
+
+
{{'view.server.config.bot.message_delete_timer' | translate}}:
+ +
+
+ +
+
+
{{'view.server.config.bot.notification_chat_id' | translate}}:
+ +
+
+ +
+
+
{{'view.server.config.bot.max_voice_state_hours' | translate}}:
+ +
+
+ +
+
+
{{'view.server.config.bot.xp_per_message' | translate}}:
+ +
+
+ +
+
+
{{'view.server.config.bot.xp_per_reaction' | translate}}:
+ +
+
+ +
+
+
{{'view.server.config.bot.max_message_xp_per_hour' | translate}}:
+ +
+
+ +
+
+
{{'view.server.config.bot.xp_per_ontime_hour' | translate}}:
+ +
+
+ +
+
+
{{'view.server.config.bot.xp_per_event_participation' | translate}}:
+ +
+
+ +
+
+
{{'view.server.config.bot.xp_per_achievement' | translate}}:
+ +
+
+ +
+
+
{{'view.server.config.bot.afk_command_channel_id' | translate}}:
+ +
+
+ +
+
+
{{'view.server.config.bot.help_voice_channel_id' | translate}}:
+ +
+
+ +
+
+
{{'view.server.config.bot.team_channel_id' | translate}}:
+ +
+
+ +
+
+
{{'view.server.config.bot.login_message_channel_id' | translate}}:
+ +
+
+ +
+ + + + +
+ +
+ +
+
diff --git a/kdb-web/src/app/modules/view/server/config/components/config/config.component.scss b/kdb-web/src/app/modules/view/server/config/components/config/config.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/view/server/config/components/config/config.component.spec.ts b/kdb-web/src/app/modules/view/server/config/components/config/config.component.spec.ts new file mode 100644 index 00000000..94dd19ba --- /dev/null +++ b/kdb-web/src/app/modules/view/server/config/components/config/config.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConfigComponent } from './config.component'; + +describe('ConfigComponent', () => { + let component: ConfigComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ConfigComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ConfigComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/view/server/config/components/config/config.component.ts b/kdb-web/src/app/modules/view/server/config/components/config/config.component.ts new file mode 100644 index 00000000..0de50e7c --- /dev/null +++ b/kdb-web/src/app/modules/view/server/config/components/config/config.component.ts @@ -0,0 +1,116 @@ +import { Component, OnInit } from "@angular/core"; +import { FormBuilder } from "@angular/forms"; +import { TranslateService } from "@ngx-translate/core"; +import { catchError } from "rxjs/operators"; +import { GuiService } from "src/app/services/gui/gui.service"; +import { SettingsService } from "src/app/services/settings/settings.service"; +import { SpinnerService } from "src/app/services/spinner/spinner.service"; +import { ToastService } from "src/app/services/toast/toast.service"; +import { throwError } from "rxjs"; +import { Query, ServerConfigQuery } from "../../../../../../models/graphql/query.model"; +import { Queries } from "../../../../../../models/graphql/queries.model"; +import { DataService } from "../../../../../../services/data/data.service"; +import { ServerConfigMutationResult } from "../../../../../../models/graphql/result.model"; +import { Mutations } from "../../../../../../models/graphql/mutations.model"; +import { AuthService } from "../../../../../../services/auth/auth.service"; +import { ServerConfig } from "../../../../../../models/config/server-config.model"; +import { Server } from "../../../../../../models/data/server.model"; +import { ActivatedRoute } from "@angular/router"; +import { Table } from "primeng/table"; + +type AFKChannelId = { + id: number; + value: string; +}; + +@Component({ + selector: "app-config", + templateUrl: "./config.component.html", + styleUrls: ["./config.component.scss"] +}) +export class ConfigComponent implements OnInit { + config: ServerConfig = { + messageDeleteTimer: 0, + afkChannelIds: [], + moderatorRoleIds: [], + adminRoleIds: [] + }; + + + afkChannelIds: AFKChannelId[] = []; + clonedAfkChannelIds: { [s: number]: AFKChannelId } = {}; + + private server: Server = {}; + + constructor( + private data: DataService, + private settingsService: SettingsService, + private spinnerService: SpinnerService, + private guiService: GuiService, + private formBuilder: FormBuilder, + private toastService: ToastService, + private translate: TranslateService, + private authService: AuthService, + private spinner: SpinnerService, + private route: ActivatedRoute + ) { + } + + ngOnInit(): void { + this.spinnerService.showSpinner(); + + this.data.getServerFromRoute(this.route).then(async server => { + this.server = server; + this.loadConfig(); + }); + } + + loadConfig() { + this.data.query(Queries.serverConfigQuery, { + serverId: this.server.id + }, + (data: Query) => { + return data.servers[0]; + }).subscribe(data => { + this.config = data.config; + + let id = 0; + for (const afkChannelId of this.config.afkChannelIds ?? []) { + this.afkChannelIds.push({ id: id, value: afkChannelId }); + id++; + } + + this.spinnerService.hideSpinner(); + }); + } + + saveServerConfig() { + this.spinner.showSpinner(); + this.data.mutation(Mutations.updateServerConfig, { + id: this.config.id, + messageDeleteTimer: this.config.messageDeleteTimer, + notificationChatId: this.config.notificationChatId, + maxVoiceStateHours: this.config.maxVoiceStateHours, + xpPerMessage: this.config.xpPerMessage, + xpPerReaction: this.config.xpPerReaction, + maxMessageXpPerHour: this.config.maxMessageXpPerHour, + xpPerOntimeHour: this.config.xpPerOntimeHour, + xpPerEventParticipation: this.config.xpPerEventParticipation, + xpPerAchievement: this.config.xpPerAchievement, + afkCommandChannelId: this.config.afkCommandChannelId, + helpVoiceChannelId: this.config.helpVoiceChannelId, + teamChannelId: this.config.teamChannelId, + loginMessageChannelId: this.config.loginMessageChannelId, + afkChannelIds: this.config.afkChannelIds, + moderatorRoleIds: this.config.moderatorRoleIds, + adminRoleIds: this.config.adminRoleIds + } + ).pipe(catchError(err => { + this.spinner.hideSpinner(); + return throwError(err); + })).subscribe(result => { + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.config.message.technician_config_create"), this.translate.instant("view.server.config.message.technician_config_create_d")); + }); + } +} diff --git a/kdb-web/src/app/modules/view/server/config/config-routing.module.ts b/kdb-web/src/app/modules/view/server/config/config-routing.module.ts new file mode 100644 index 00000000..afbbd84c --- /dev/null +++ b/kdb-web/src/app/modules/view/server/config/config-routing.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { ConfigComponent } from "./components/config/config.component"; + +const routes: Routes = [ + {path: '', component: ConfigComponent}, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class ConfigRoutingModule { } diff --git a/kdb-web/src/app/modules/view/server/config/config.module.ts b/kdb-web/src/app/modules/view/server/config/config.module.ts new file mode 100644 index 00000000..0dd2131b --- /dev/null +++ b/kdb-web/src/app/modules/view/server/config/config.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +import { ConfigRoutingModule } from './config-routing.module'; +import { ConfigComponent } from './components/config/config.component'; +import { SharedModule } from "../../../shared/shared.module"; + + +@NgModule({ + declarations: [ + ConfigComponent + ], + imports: [ + CommonModule, + ConfigRoutingModule, + SharedModule, + ] +}) +export class ConfigModule { } diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts index ae4e48ce..63e1e446 100644 --- a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts +++ b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts @@ -196,7 +196,6 @@ export class LevelsComponent implements OnInit, OnDestroy { ).pipe(catchError(err => { this.isEditingNew = false; this.spinner.hideSpinner(); - this.toastService.error(this.translate.instant("view.server.levels.message.level_create_failed"), this.translate.instant("view.server.levels.message.level_create_failed_d")); return throwError(err); })).subscribe(result => { this.isEditingNew = false; @@ -217,7 +216,6 @@ export class LevelsComponent implements OnInit, OnDestroy { } ).pipe(catchError(err => { this.spinner.hideSpinner(); - this.toastService.error(this.translate.instant("view.server.levels.message.level_update_failed"), this.translate.instant("view.server.levels.message.level_update_failed_d", { name: newLevel.name })); return throwError(err); })).subscribe(_ => { this.spinner.hideSpinner(); @@ -249,7 +247,6 @@ export class LevelsComponent implements OnInit, OnDestroy { } ).pipe(catchError(err => { this.spinner.hideSpinner(); - this.toastService.error(this.translate.instant("view.server.levels.message.level_delete_failed"), this.translate.instant("view.server.levels.message.level_delete_failed_d", { name: level.name })); return throwError(err); })).subscribe(l => { this.spinner.hideSpinner(); diff --git a/kdb-web/src/app/modules/view/server/members/members.component.ts b/kdb-web/src/app/modules/view/server/members/members.component.ts index 9cf115d1..e46afb61 100644 --- a/kdb-web/src/app/modules/view/server/members/members.component.ts +++ b/kdb-web/src/app/modules/view/server/members/members.component.ts @@ -237,7 +237,6 @@ export class MembersComponent implements OnInit, OnDestroy { } ).pipe(catchError(err => { this.spinner.hideSpinner(); - this.toastService.error(this.translate.instant("view.server.members.message.user_change_failed"), this.translate.instant("view.server.members.message.user_change_failed_d", { name: newUser.name })); return throwError(err); })).subscribe(_ => { this.spinner.hideSpinner(); diff --git a/kdb-web/src/app/modules/view/server/server-routing.module.ts b/kdb-web/src/app/modules/view/server/server-routing.module.ts index a83dab96..c5626e9b 100644 --- a/kdb-web/src/app/modules/view/server/server-routing.module.ts +++ b/kdb-web/src/app/modules/view/server/server-routing.module.ts @@ -10,7 +10,8 @@ const routes: Routes = [ { path: "members/:memberId", component: ProfileComponent }, { path: "auto-roles", loadChildren: () => import("./auto-role/auto-role.module").then(m => m.AutoRoleModule) }, { path: "levels", loadChildren: () => import("./levels/levels.module").then(m => m.LevelsModule) }, - { path: "achievements", loadChildren: () => import("./achievements/achievements.module").then(m => m.AchievementsModule) } + { path: "achievements", loadChildren: () => import("./achievements/achievements.module").then(m => m.AchievementsModule) }, + { path: "config", loadChildren: () => import("./config/config.module").then(m => m.ConfigModule) } ]; @NgModule({ diff --git a/kdb-web/src/app/services/data/data.service.ts b/kdb-web/src/app/services/data/data.service.ts index 54d13057..9d7d13b3 100644 --- a/kdb-web/src/app/services/data/data.service.ts +++ b/kdb-web/src/app/services/data/data.service.ts @@ -10,6 +10,8 @@ import { Query } from "../../models/graphql/query.model"; import { SidebarService } from "../sidebar/sidebar.service"; import { SpinnerService } from "../spinner/spinner.service"; import { GraphQLResult } from "../../models/graphql/result.model"; +import { ToastService } from "../toast/toast.service"; +import { TranslateService } from "@ngx-translate/core"; @Injectable({ providedIn: "root" @@ -21,7 +23,9 @@ export class DataService { private http: HttpClient, private sidebar: SidebarService, private spinner: SpinnerService, - private router: Router + private router: Router, + private toast: ToastService, + private translate: TranslateService, ) { } @@ -72,6 +76,10 @@ export class DataService { }) .pipe(map(d => { if (d.errors && d.errors.length > 0) { + d.errors.forEach((error: Error) => { + this.toast.error(this.translate.instant("common.error"), error.message) + }); + throw new Error(d.errors.toString()); } return d.data; diff --git a/kdb-web/src/app/services/sidebar/sidebar.service.ts b/kdb-web/src/app/services/sidebar/sidebar.service.ts index 81ab4548..196b7e25 100644 --- a/kdb-web/src/app/services/sidebar/sidebar.service.ts +++ b/kdb-web/src/app/services/sidebar/sidebar.service.ts @@ -3,7 +3,7 @@ import { MenuItem } from "primeng/api"; import { BehaviorSubject } from "rxjs"; import { AuthRoles } from "../../models/auth/auth-roles.enum"; import { AuthService } from "../auth/auth.service"; -import { LangChangeEvent, TranslateService } from "@ngx-translate/core"; +import { TranslateService } from "@ngx-translate/core"; import { NavigationEnd, Router } from "@angular/router"; import { ThemeService } from "../theme/theme.service"; import { Server } from "../../models/data/server.model"; @@ -25,6 +25,7 @@ export class SidebarService { serverAutoRoles: MenuItem = {}; serverLevels: MenuItem = {}; serverAchievements: MenuItem = {}; + serverConfig: MenuItem = {}; serverMenu: MenuItem = {}; adminConfig: MenuItem = {}; adminUsers: MenuItem = {}; @@ -110,12 +111,19 @@ export class SidebarService { routerLink: `server/${this.server$.value?.id}/achievements` }; + this.serverConfig = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.config") : "", + icon: "pi pi-cog", + visible: true, + routerLink: `server/${this.server$.value?.id}/config` + }; + this.serverMenu = { label: this.isSidebarOpen ? this.server$.value?.name : "", icon: "pi pi-server", visible: false, expanded: true, - items: [this.serverDashboard, this.serverProfile, this.serverMembers, this.serverAutoRoles, this.serverLevels, this.serverAchievements] + items: [this.serverDashboard, this.serverProfile, this.serverMembers, this.serverAutoRoles, this.serverLevels, this.serverAchievements, this.serverConfig] }; this.adminConfig = { label: this.isSidebarOpen ? this.translateService.instant("sidebar.config") : "", @@ -151,6 +159,7 @@ export class SidebarService { this.serverAutoRoles.visible = !!user?.isModerator; this.serverLevels.visible = !!user?.isModerator; this.serverAchievements.visible = !!user?.isModerator; + this.serverConfig.visible = !!user?.isAdmin; } else { this.serverMenu.visible = false; } diff --git a/kdb-web/src/assets/config.json b/kdb-web/src/assets/config.json index a2d9a6c2..581bbcb8 100644 --- a/kdb-web/src/assets/config.json +++ b/kdb-web/src/assets/config.json @@ -5,7 +5,7 @@ "WebVersion": { "Major": "1", "Minor": "0", - "Micro": "dev268_achievements" + "Micro": "dev127_config_in_wi" }, "Themes": [ { diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index 7deee1ea..f346df54 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -32,6 +32,15 @@ "users": "Benutzer" }, "settings": { + "bot": { + "cache_max_messages": "Anzahl der Nachrichten im cache", + "header": "Bot", + "help_url": "Befehlsreferenz", + "ping_urls": "Ping Adressen", + "technician_ids": "Techniker Ids", + "wait_for_restart": "Wartezeit vor Neustart", + "wait_for_shutdown": "Wartezeit vor Herunterfahren" + }, "email": { "email_address": "E-Mail-Adresse", "header": "E-Mail", @@ -51,6 +60,10 @@ "send_failed": "Senden fehlgeschlagen", "send_mail": "E-Mail wurde erfolgreich gesendet", "success": "Erfolg", + "technician_config_create": "Konfiguration gespeichert", + "technician_config_create_d": "Konfiguration erfolgreich gespeichert", + "technician_config_create_failed": "Speichern fehlgeschlagen", + "technician_config_create_failed_d": "Speichern der Konfiguration ist fehlgeschlagen!", "test_mail_not_send": "Die Test E-Mail konnte nicht gesendet werden!" }, "website": { @@ -130,6 +143,7 @@ "email": "E-Mail", "error": "Fehler", "history": { + "attribute": "Attribut", "autoRole": "Auto Rolle", "channelId": "Kanal Id", "color": "Farbe", @@ -142,15 +156,14 @@ "id": "Id", "leftServer": "Server verlassen", "messageId": "Nachricht Id", - "minXp": "Min. XP", + "min_xp": "Min. XP", "name": "Name", + "operator": "Operator", "permissions": "Berechtigung", "roleId": "Rolle", "server": "Server", - "xp": "XP", - "attribute": "Attribut", - "operator": "Operator", - "value": "Wert" + "value": "Wert", + "xp": "XP" }, "id": "Id", "joined_at": "Beigetreten am", @@ -159,7 +172,8 @@ "name": "Name", "no_entries_found": "Keine Einträge gefunden", "of": "von", - "reset_filters": "Filter zurücksetzen" + "reset_filters": "Filter zurücksetzen", + "save": "Speichern" }, "dialog": { "abort": "Abbrechen", @@ -325,8 +339,8 @@ "header": "Errungenschaften", "headers": { "attribute": "Attribut", - "name": "Name", "description": "Beschreibung", + "name": "Name", "operator": "Operator", "value": "Wert" }, @@ -393,6 +407,28 @@ } } }, + "config": { + "bot": { + "admin_roles": "Admin Rollen", + "afk_channels": "AFK Sprachkanäle", + "afk_command_channel_id": "AFK Kanal für den Befehl /afk", + "header": "Bot Konfiguration", + "help_voice_channel_id": "Sprachkanal für Hilfsbenachrichtung", + "login_message_channel_id": "Kanal für die Nachricht vom Bot nach Start", + "max_message_xp_per_hour": "Maximale XP pro Stunde durch Nachrichten", + "max_voice_state_hours": "Maximale Stunden für eine ontime nach Bot neustart", + "message_delete_timer": "Zeit bis zum löschen einer Botnachricht in sekunden", + "moderator_roles": "Moderator Rollen", + "notification_chat_id": "Benachrichtungskanal", + "team_channel_id": "Team chat", + "xp_per_achievement": "XP für Errungenschaft", + "xp_per_event_participation": "XP für Event Teilnahme", + "xp_per_message": "XP für eine Nachricht", + "xp_per_ontime_hour": "XP für eine Stunde im Sprachkanal", + "xp_per_reaction": "XP für eine Reaktion" + }, + "header": "Server Konfiguration" + }, "dashboard": { "deleted_message_count": "Gelöschte Nachrichten", "header": "Server dashboard", diff --git a/kdb-web/src/assets/i18n/en.json b/kdb-web/src/assets/i18n/en.json index b4e584ad..7dd4fa29 100644 --- a/kdb-web/src/assets/i18n/en.json +++ b/kdb-web/src/assets/i18n/en.json @@ -32,6 +32,15 @@ "users": "User" }, "settings": { + "bot": { + "cache_max_messages": "Number of messages in cache", + "header": "Bot", + "help_url": "Help URL", + "ping_urls": "Ping addresses", + "technician_ids": "Technician Ids", + "wait_for_restart": "Time to wait before restart", + "wait_for_shutdown": "Time to wait before shutdown" + }, "email": { "email_address": "E-Mail address", "header": "E-Mail", @@ -51,6 +60,10 @@ "send_failed": "Sending failed", "send_mail": "Email was sent successfully", "success": "Success", + "technician_config_create": "Config saved", + "technician_config_create_d": "Config saved successfully", + "technician_config_create_failed": "Saving config failed", + "technician_config_create_failed_d": "Saving config failed!", "test_mail_not_send": "Test email could not be sent!" }, "website": { @@ -130,6 +143,7 @@ "email": "E-Mail", "error": "Error", "history": { + "attribute": "Attribute", "autoRole": "Auto role", "channelId": "Channel Id", "color": "Color", @@ -142,15 +156,14 @@ "id": "Id", "leftServer": "Left server", "messageId": "Message Id", - "minXp": "Min. XP", + "min_xp": "Min. XP", "name": "Name", + "operator": "Operator", "permissions": "Permissions", "roleId": "Role", "server": "Server", - "xp": "XP", - "attribute": "Attribute", - "operator": "Operator", - "value": "Value" + "value": "Value", + "xp": "XP" }, "id": "Id", "joined_at": "Joined at", @@ -159,7 +172,8 @@ "name": "Name", "no_entries_found": "No entries found", "of": "of", - "reset_filters": "Reset filters" + "reset_filters": "Reset filters", + "save": "Save" }, "dialog": { "abort": "Abort", @@ -325,6 +339,7 @@ "header": "Achievements", "headers": { "attribute": "Attribute", + "description": "Description", "name": "Namer", "operator": "Operator", "value": "Value" @@ -392,6 +407,28 @@ } } }, + "config": { + "bot": { + "admin_roles": "Admin Roles", + "afk_channels": "AFK Voicechannel", + "afk_command_channel_id": "AFK Channel for the command /afk", + "header": "Bot configuration", + "help_voice_channel_id": "Voicechannel für help notifications", + "login_message_channel_id": "Channel for bot message after start", + "max_message_xp_per_hour": "Max xp per hour with message", + "max_voice_state_hours": "Max ontime hours after bot restart", + "message_delete_timer": "Time to wait before delete bot messages", + "moderator_roles": "Moderator roles", + "notification_chat_id": "Notification channel", + "team_channel_id": "Team chat", + "xp_per_achievement": "XP for achievement", + "xp_per_event_participation": "XP for event participation", + "xp_per_message": "XP for message", + "xp_per_ontime_hour": "XP for one hour in an voice channel", + "xp_per_reaction": "XP for an reaction" + }, + "header": "Server configuration" + }, "dashboard": { "deleted_message_count": "Deleted messages", "header": "Server dashboard", @@ -472,7 +509,7 @@ "ontime": "Ontime", "permission_denied": "Access denied!", "permission_denied_d": "You have to be moderator to see other profiles!", - "xp": "Xp" + "xp": "XP" } }, "user_settings": { diff --git a/kdb-web/src/styles.scss b/kdb-web/src/styles.scss index b9318b03..71be66ee 100644 --- a/kdb-web/src/styles.scss +++ b/kdb-web/src/styles.scss @@ -177,6 +177,14 @@ header { font-size: 18px; } + .content-data-value-row { + display: flex; + flex: 1; + flex-direction: column; + + font-size: 18px; + } + .content-divider { margin: 5px 0; } @@ -477,6 +485,7 @@ footer { .right { width: 50%; text-align: right; + .p-button-label { font-weight: unset !important; }