From 9201cbf35713e0b7e59861d7195170dde9c0b3a8 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 18 Apr 2023 20:33:59 +0200 Subject: [PATCH 001/127] Fixed bug that mods cannot see auto role rules --- kdb-bot/src/bot_graphql/abc/query_abc.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kdb-bot/src/bot_graphql/abc/query_abc.py b/kdb-bot/src/bot_graphql/abc/query_abc.py index 9c8f3ef1..a0435218 100644 --- a/kdb-bot/src/bot_graphql/abc/query_abc.py +++ b/kdb-bot/src/bot_graphql/abc/query_abc.py @@ -2,6 +2,7 @@ from typing import Callable from ariadne import ObjectType from cpl_core.dependency_injection import ServiceProviderABC +from cpl_core.type import T from cpl_discord.service import DiscordBotServiceABC from cpl_query.extension import List @@ -66,7 +67,7 @@ class QueryABC(ObjectType): self.set_field(f"{name}Count", lambda *args: wrapper(*args).count()) @ServiceProviderABC.inject - def _can_user_see_element(self, user: AuthUser, element, services: ServiceProviderABC) -> bool: + def _can_user_see_element(self, user: AuthUser, element: T, services: ServiceProviderABC) -> bool: permissions: PermissionService = services.get_service(PermissionService) bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC) @@ -82,12 +83,12 @@ class QueryABC(ObjectType): break elif type(element) == AutoRoleRule: - element: AutoRole = element + element: AutoRoleRule = element for u in user.users: u: User = u guild = bot.get_guild(u.server.discord_id) member = guild.get_member(u.discord_id) - if permissions.is_member_moderator(member) and u.server.id == element.server.id: + if permissions.is_member_moderator(member) and u.server.id == element.auto_role.server.id: access = True break -- 2.45.2 From bd8bd40863c64a9ea8e19559178245b44d3763c0 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 8 Jun 2023 08:47:56 +0200 Subject: [PATCH 002/127] Added reaction channel null check #318 --- kdb-bot/src/modules/base/helper/base_reaction_handler.py | 4 ++++ 1 file changed, 4 insertions(+) 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 9fb4f89e..a16c2cf4 100644 --- a/kdb-bot/src/modules/base/helper/base_reaction_handler.py +++ b/kdb-bot/src/modules/base/helper/base_reaction_handler.py @@ -47,6 +47,10 @@ class BaseReactionHandler: log_msg += f" with {payload.emoji.name}" try: channel = guild.get_channel(payload.channel_id) + if channel is None: + self._logger.warn(__name__, f"Channel not found") + return + message = await channel.fetch_message(payload.message_id) self._logger.info( __name__, -- 2.45.2 From 6e0d4a5144263d3a12e0e78b5b53b5f14b936590 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sat, 8 Jul 2023 09:40:20 +0200 Subject: [PATCH 003/127] Add xp when event starts #323 --- .../base_on_scheduled_event_update_event.py | 6 ++- ...tate_update_event_scheduled_event_bonus.py | 28 +------------- .../src/modules/base/service/event_service.py | 37 ++++++++++++++++++- 3 files changed, 42 insertions(+), 29 deletions(-) diff --git a/kdb-bot/src/modules/base/events/base_on_scheduled_event_update_event.py b/kdb-bot/src/modules/base/events/base_on_scheduled_event_update_event.py index 5b9cf901..640a9a80 100644 --- a/kdb-bot/src/modules/base/events/base_on_scheduled_event_update_event.py +++ b/kdb-bot/src/modules/base/events/base_on_scheduled_event_update_event.py @@ -26,7 +26,11 @@ class BaseOnScheduledEventUpdateEvent(OnScheduledEventUpdateABC): # save started event if before.status != after.status and after.status == EventStatus.active: - self._events.add_event(ActiveEvent(after)) + active_event = ActiveEvent(after) + self._events.add_event(active_event) + + for member in after.channel.members: + self._events.give_xp_for_event_participation(member, active_event) # delete stopped event if before.status != after.status and ( after.status.value == EventStatus.cancelled.value or after.status.value == EventStatus.completed.value 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..871d7563 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 @@ -1,36 +1,20 @@ import discord -from cpl_core.configuration import ConfigurationABC -from cpl_core.database.context import DatabaseContextABC from cpl_core.logging import LoggerABC 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 modules.base.service.event_service import EventService class BaseOnVoiceStateUpdateEventScheduledEventBonus(OnVoiceStateUpdateABC): def __init__( self, - config: ConfigurationABC, logger: LoggerABC, - base_helper: BaseHelperABC, - servers: ServerRepositoryABC, - users: UserRepositoryABC, events: EventService, - db: DatabaseContextABC, ): OnVoiceStateUpdateABC.__init__(self) - self._config = config self._logger = logger - self._base_helper = base_helper - self._servers = servers - self._users = users self._events = events - self._db = db self._logger.info(__name__, f"Module {type(self)} loaded") @@ -51,16 +35,6 @@ class BaseOnVoiceStateUpdateEventScheduledEventBonus(OnVoiceStateUpdateABC): self._logger.debug(__name__, f"Module {type(self)} stopped") return - server = self._servers.get_server_by_discord_id(member.guild.id) - user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) - if active_event.participants.any(lambda x: x.id == user.id): - self._logger.debug(__name__, f"Module {type(self)} stopped") - return - - settings: BaseServerSettings = self._base_helper.get_config(server.discord_id) - user.xp += settings.xp_per_event_participation - self._users.update_user(user) - self._db.save_changes() - active_event.participants.append(user) + self._events.give_xp_for_event_participation(member, active_event) self._logger.debug(__name__, f"Module {type(self)} stopped") diff --git a/kdb-bot/src/modules/base/service/event_service.py b/kdb-bot/src/modules/base/service/event_service.py index 8073b3d3..d5c77360 100644 --- a/kdb-bot/src/modules/base/service/event_service.py +++ b/kdb-bot/src/modules/base/service/event_service.py @@ -1,13 +1,35 @@ from typing import Optional import discord +from cpl_core.configuration import ConfigurationABC +from cpl_core.database.context import DatabaseContextABC +from cpl_core.logging import LoggerABC from cpl_query.extension import List +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.user_repository_abc import UserRepositoryABC +from modules.base.configuration.base_server_settings import BaseServerSettings from modules.base.model.active_event import ActiveEvent +from modules.base.service.base_helper_service import BaseHelperService class EventService: - def __init__(self): + def __init__( + self, + config: ConfigurationABC, + logger: LoggerABC, + base_helper: BaseHelperService, + servers: ServerRepositoryABC, + users: UserRepositoryABC, + db: DatabaseContextABC, + ): + self._config = config + self._logger = logger + self._base_helper = base_helper + self._servers = servers + self._users = users + self._db = db + self._active_events = List(ActiveEvent) def add_event(self, event: ActiveEvent): @@ -29,3 +51,16 @@ class EventService: return self._active_events.remove(event) + + def give_xp_for_event_participation(self, member: discord.Member, active_event: ActiveEvent): + server = self._servers.get_server_by_discord_id(member.guild.id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) + if active_event.participants.any(lambda x: x.id == user.id): + self._logger.debug(__name__, f"Module {type(self)} stopped") + return + + settings: BaseServerSettings = self._base_helper.get_config(server.discord_id) + user.xp += settings.xp_per_event_participation + self._users.update_user(user) + self._db.save_changes() + active_event.participants.append(user) -- 2.45.2 From 9f614e8a31912ea95edd180312b26e2214dcf2cf Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sat, 8 Jul 2023 09:59:50 +0200 Subject: [PATCH 004/127] Repaired config for support --- kdb-bot/src/bot/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kdb-bot/src/bot/config b/kdb-bot/src/bot/config index 0c946375..7063c9e7 160000 --- a/kdb-bot/src/bot/config +++ b/kdb-bot/src/bot/config @@ -1 +1 @@ -Subproject commit 0c9463753731ab1f5d0f916d21ac7ea304742995 +Subproject commit 7063c9e7c08a6ad812533c1a09e8438c4b2a22ac -- 2.45.2 From 6d14ba9d790b3a2715f4e5ddfea07ab4a7d9d0c0 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 12 Jun 2023 20:52:01 +0200 Subject: [PATCH 005/127] Updated packages #297_cpl_update --- kdb-bot/src/bot/bot.json | 18 +++++++++--------- kdb-bot/src/bot_graphql/bot-graphql.json | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/kdb-bot/src/bot/bot.json b/kdb-bot/src/bot/bot.json index 507da098..dd99aa8d 100644 --- a/kdb-bot/src/bot/bot.json +++ b/kdb-bot/src/bot/bot.json @@ -16,23 +16,23 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "cpl-core==2022.12.1.post3", - "cpl-translation==2022.12.1", - "cpl-query==2022.12.2.post2", - "cpl-discord==2022.12.2.post1", - "Flask==2.2.2", + "cpl-core==2023.4.0.post1", + "cpl-translation==2023.4.0", + "cpl-query==2023.4.0", + "cpl-discord==2023.4.0", + "Flask==2.3.2", "Flask-Classful==0.14.2", "Flask-Cors==3.0.10", - "PyJWT==2.6.0", + "PyJWT==2.7.0", "waitress==2.1.2", - "Flask-SocketIO==5.3.2", + "Flask-SocketIO==5.3.4", "eventlet==0.33.3", "requests-oauthlib==1.3.1", "icmplib==3.0.3", - "ariadne==0.17.1" + "ariadne==0.19.1" ], "DevDependencies": [ - "cpl-cli==2022.12.1.post3", + "cpl-cli==2023.4.0.post1", "pygount==1.5.1" ], "PythonVersion": ">=3.10.4", diff --git a/kdb-bot/src/bot_graphql/bot-graphql.json b/kdb-bot/src/bot_graphql/bot-graphql.json index bab3a067..5b48b407 100644 --- a/kdb-bot/src/bot_graphql/bot-graphql.json +++ b/kdb-bot/src/bot_graphql/bot-graphql.json @@ -16,10 +16,10 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "cpl-core>=1.0.7" + "cpl-core==2022.12.0" ], "DevDependencies": [ - "cpl-cli>=1.0.7" + "cpl-core==2022.12.0" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, -- 2.45.2 From 8a2edc7228146857316b7405a7fe48e1ef441505 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 13 Jun 2023 16:16:52 +0200 Subject: [PATCH 006/127] Updated stuff #297_cpl_update --- kdb-bot/src/bot/bot.json | 10 ++-- kdb-bot/src/bot/config | 2 +- .../bot_api/controller/graphql_controller.py | 4 +- .../configuration/bot_logging_settings.py | 47 ++++++++++++------- .../configuration/file_logging_settings.py | 32 +++++++------ 5 files changed, 55 insertions(+), 40 deletions(-) diff --git a/kdb-bot/src/bot/bot.json b/kdb-bot/src/bot/bot.json index dd99aa8d..41e95b38 100644 --- a/kdb-bot/src/bot/bot.json +++ b/kdb-bot/src/bot/bot.json @@ -16,10 +16,10 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "cpl-core==2023.4.0.post1", - "cpl-translation==2023.4.0", - "cpl-query==2023.4.0", - "cpl-discord==2023.4.0", + "cpl-core==2023.4.0.post2", + "cpl-translation==2023.4.0.post1", + "cpl-query==2023.4.0.post1", + "cpl-discord==2023.4.0.post2", "Flask==2.3.2", "Flask-Classful==0.14.2", "Flask-Cors==3.0.10", @@ -32,7 +32,7 @@ "ariadne==0.19.1" ], "DevDependencies": [ - "cpl-cli==2023.4.0.post1", + "cpl-cli==2023.4.0.post3", "pygount==1.5.1" ], "PythonVersion": ">=3.10.4", diff --git a/kdb-bot/src/bot/config b/kdb-bot/src/bot/config index 0c946375..e1c1efac 160000 --- a/kdb-bot/src/bot/config +++ b/kdb-bot/src/bot/config @@ -1 +1 @@ -Subproject commit 0c9463753731ab1f5d0f916d21ac7ea304742995 +Subproject commit e1c1efac984a04826c0c2713a26129b9d34b21d6 diff --git a/kdb-bot/src/bot_api/controller/graphql_controller.py b/kdb-bot/src/bot_api/controller/graphql_controller.py index d9072029..aefd8f13 100644 --- a/kdb-bot/src/bot_api/controller/graphql_controller.py +++ b/kdb-bot/src/bot_api/controller/graphql_controller.py @@ -1,5 +1,5 @@ from ariadne import graphql_sync -from ariadne.constants import PLAYGROUND_HTML +from ariadne.explorer import ExplorerGraphiQL from cpl_core.configuration import ConfigurationABC from cpl_core.environment import ApplicationEnvironmentABC from flask import request, jsonify @@ -30,7 +30,7 @@ class GraphQLController: if self._env.environment_name != "development": return "", 403 - return PLAYGROUND_HTML, 200 + return ExplorerGraphiQL().html(None), 200 @Route.post(f"{BasePath}") @Route.authorize(by_api_key=True) 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 b69e2c73..a91c5638 100644 --- a/kdb-bot/src/bot_core/configuration/bot_logging_settings.py +++ b/kdb-bot/src/bot_core/configuration/bot_logging_settings.py @@ -1,32 +1,43 @@ -import traceback - from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console, ForegroundColorEnum +from cpl_core.utils.json_processor import JSONProcessor from cpl_query.extension import List from bot_core.configuration.file_logging_settings import FileLoggingSettings class BotLoggingSettings(ConfigurationModelABC): - def __init__(self): + def __init__(self, custom_logs: dict = None): ConfigurationModelABC.__init__(self) self._files: List[FileLoggingSettings] = List(FileLoggingSettings) + if custom_logs is not None: + self._files_from_dict(custom_logs) + @property def files(self) -> List[FileLoggingSettings]: return self._files - def from_dict(self, settings: dict): - try: - files = List(FileLoggingSettings) - for s in settings: - st = FileLoggingSettings() - settings[s]["Key"] = s - st.from_dict(settings[s]) - files.append(st) - self._files = files - except Exception as e: - Console.set_foreground_color(ForegroundColorEnum.red) - Console.write_line(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings") - Console.write_line(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") - Console.set_foreground_color(ForegroundColorEnum.default) + def _files_from_dict(self, settings: dict): + files = List(FileLoggingSettings) + for s in settings: + # st = FileLoggingSettings(s) + settings[s]["Key"] = s + # st.from_dict(settings[s]) + st = JSONProcessor.process(FileLoggingSettings, settings[s]) + files.append(st) + self._files = files + + # def from_dict(self, settings: dict): + # try: + # files = List(FileLoggingSettings) + # for s in settings: + # st = FileLoggingSettings() + # settings[s]["Key"] = s + # st.from_dict(settings[s]) + # files.append(st) + # self._files = files + # except Exception as e: + # Console.set_foreground_color(ForegroundColorEnum.red) + # Console.write_line(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings") + # Console.write_line(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") + # Console.set_foreground_color(ForegroundColorEnum.default) 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 58d461b9..b941601d 100644 --- a/kdb-bot/src/bot_core/configuration/file_logging_settings.py +++ b/kdb-bot/src/bot_core/configuration/file_logging_settings.py @@ -1,23 +1,27 @@ -import traceback - -from cpl_core.console import Console -from cpl_core.logging import LoggingSettings +from cpl_core.logging import LoggingSettings, LoggingLevelEnum class FileLoggingSettings(LoggingSettings): - def __init__(self): - LoggingSettings.__init__(self) + def __init__( + self, + key: str, + path: str = None, + filename: str = None, + console_log_level: LoggingLevelEnum = None, + file_log_level: LoggingLevelEnum = None, + ): + LoggingSettings.__init__(self, path, filename, console_log_level, file_log_level) - self._key = "" + self._key = key @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()}") + # 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()}") -- 2.45.2 From 2e9cf0bd9734db119af839b2755194699f523e05 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 13 Jun 2023 16:24:38 +0200 Subject: [PATCH 007/127] Updated cpl-discord #297_cpl_update --- kdb-bot/src/bot/bot.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kdb-bot/src/bot/bot.json b/kdb-bot/src/bot/bot.json index 41e95b38..54f2ec06 100644 --- a/kdb-bot/src/bot/bot.json +++ b/kdb-bot/src/bot/bot.json @@ -19,7 +19,7 @@ "cpl-core==2023.4.0.post2", "cpl-translation==2023.4.0.post1", "cpl-query==2023.4.0.post1", - "cpl-discord==2023.4.0.post2", + "cpl-discord==2023.4.0.post3", "Flask==2.3.2", "Flask-Classful==0.14.2", "Flask-Cors==3.0.10", -- 2.45.2 From dbd82930d42a3ea4d25394eb867c7cfa4e6e0967 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 14 Jun 2023 09:00:19 +0200 Subject: [PATCH 008/127] Removed comments #297_cpl_update --- .../configuration/bot_logging_settings.py | 17 ----------------- 1 file changed, 17 deletions(-) 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 a91c5638..1c0fb22a 100644 --- a/kdb-bot/src/bot_core/configuration/bot_logging_settings.py +++ b/kdb-bot/src/bot_core/configuration/bot_logging_settings.py @@ -20,24 +20,7 @@ class BotLoggingSettings(ConfigurationModelABC): def _files_from_dict(self, settings: dict): files = List(FileLoggingSettings) for s in settings: - # st = FileLoggingSettings(s) settings[s]["Key"] = s - # st.from_dict(settings[s]) st = JSONProcessor.process(FileLoggingSettings, settings[s]) files.append(st) self._files = files - - # def from_dict(self, settings: dict): - # try: - # files = List(FileLoggingSettings) - # for s in settings: - # st = FileLoggingSettings() - # settings[s]["Key"] = s - # st.from_dict(settings[s]) - # files.append(st) - # self._files = files - # except Exception as e: - # Console.set_foreground_color(ForegroundColorEnum.red) - # Console.write_line(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings") - # Console.write_line(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") - # Console.set_foreground_color(ForegroundColorEnum.default) -- 2.45.2 From ff16eae477a3911bcb148e32795225820aff8dcd Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 14 Jun 2023 09:25:54 +0200 Subject: [PATCH 009/127] Moved data integrity check #292_shutdown_procedure --- kdb-bot/src/bot_core/core_module.py | 2 + .../service/data_integrity_service.py | 370 ++++++++++++++++++ .../database/database_on_ready_event.py | 344 +--------------- 3 files changed, 377 insertions(+), 339 deletions(-) create mode 100644 kdb-bot/src/bot_core/service/data_integrity_service.py diff --git a/kdb-bot/src/bot_core/core_module.py b/kdb-bot/src/bot_core/core_module.py index 001dc36c..b7397b36 100644 --- a/kdb-bot/src/bot_core/core_module.py +++ b/kdb-bot/src/bot_core/core_module.py @@ -11,6 +11,7 @@ from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from bot_core.events.core_on_ready_event import CoreOnReadyEvent from bot_core.pipes.date_time_offset_pipe import DateTimeOffsetPipe from bot_core.service.client_utils_service import ClientUtilsService +from bot_core.service.data_integrity_service import DataIntegrityService from bot_core.service.message_service import MessageService @@ -24,6 +25,7 @@ class CoreModule(ModuleABC): def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): services.add_transient(MessageServiceABC, MessageService) services.add_transient(ClientUtilsABC, ClientUtilsService) + services.add_transient(DataIntegrityService) # pipes services.add_transient(DateTimeOffsetPipe) diff --git a/kdb-bot/src/bot_core/service/data_integrity_service.py b/kdb-bot/src/bot_core/service/data_integrity_service.py new file mode 100644 index 00000000..849d5261 --- /dev/null +++ b/kdb-bot/src/bot_core/service/data_integrity_service.py @@ -0,0 +1,370 @@ +from datetime import datetime, timedelta +from typing import Union + +import discord +from cpl_core.configuration import ConfigurationABC +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_core.logging.database_logger import DatabaseLogger +from bot_core.pipes.date_time_offset_pipe import DateTimeOffsetPipe +from bot_data.abc.client_repository_abc import ClientRepositoryABC +from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC +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, +) +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.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.base.configuration.base_server_settings import BaseServerSettings + + +class DataIntegrityService: + def __init__( + self, + config: ConfigurationABC, + logger: DatabaseLogger, + seeder: SeederService, + bot: DiscordBotServiceABC, + db_context: DatabaseContextABC, + server_repo: ServerRepositoryABC, + user_repo: UserRepositoryABC, + client_repo: ClientRepositoryABC, + known_users: KnownUserRepositoryABC, + user_joins: UserJoinedServerRepositoryABC, + user_joins_vc: UserJoinedVoiceChannelRepositoryABC, + user_joined_gs: UserJoinedGameServerRepositoryABC, + dtp: DateTimeOffsetPipe, + ): + self._config = config + + self._logger = logger + self._seeder = seeder + self._bot = bot + self._db_context = db_context + self._servers = server_repo + self._users = user_repo + self._clients = client_repo + self._known_users = known_users + self._user_joins = user_joins + self._user_joins_vc = user_joins_vc + self._user_joined_gs = user_joined_gs + self._dtp = dtp + + self._is_for_shutdown = False + + def _check_known_users(self): + self._logger.debug(__name__, f"Start checking KnownUsers table, {len(self._bot.users)}") + for u in self._bot.users: + u: discord.User = u + try: + if u.bot: + self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot") + continue + + user = self._known_users.find_user_by_discord_id(u.id) + if user is not None: + continue + + self._logger.warn(__name__, f"Unknown user: {u.id}") + self._logger.debug(__name__, f"Add user: {u.id}") + self._known_users.add_user(KnownUser(u.id)) + self._db_context.save_changes() + + user = self._known_users.find_user_by_discord_id(u.id) + if user is None: + self._logger.fatal(__name__, f"Cannot add user: {u.id}") + + self._logger.debug(__name__, f"Added user: {u.id}") + except Exception as e: + self._logger.error(__name__, f"Cannot get user", e) + + def _check_servers(self): + self._logger.debug(__name__, f"Start checking Servers table") + for g in self._bot.guilds: + g: discord.Guild = g + try: + server = self._servers.find_server_by_discord_id(g.id) + if server is not None: + continue + + self._logger.warn(__name__, f"Server not found in database: {g.id}") + self._logger.debug(__name__, f"Add server: {g.id}") + self._servers.add_server(Server(g.id)) + self._db_context.save_changes() + + server = self._servers.find_server_by_discord_id(g.id) + if server is None: + self._logger.fatal(__name__, f"Cannot add server: {g.id}") + + self._logger.debug(__name__, f"Added server: {g.id}") + except Exception as e: + self._logger.error(__name__, f"Cannot get server", e) + + results = self._servers.get_servers() + if results is None or len(results) == 0: + self._logger.error(__name__, f"Table Servers is empty!") + + def _check_clients(self): + self._logger.debug(__name__, f"Start checking Clients table") + for g in self._bot.guilds: + g: discord.Guild = g + try: + server: Server = self._servers.find_server_by_discord_id(g.id) + if server is None: + self._logger.fatal(__name__, f"Server not found in database: {g.id}") + + client = self._clients.find_client_by_server_id(server.id) + if client is not None: + continue + + self._logger.warn( + __name__, + f"Client for server {g.id} not found in database: {self._bot.user.id}", + ) + self._logger.debug(__name__, f"Add client: {self._bot.user.id}") + self._clients.add_client(Client(self._bot.user.id, 0, 0, 0, 0, 0, server)) + self._db_context.save_changes() + + client = self._clients.find_client_by_server_id(server.id) + if client is None: + self._logger.fatal( + __name__, + f"Cannot add client {self._bot.user.id} for server {g.id}", + ) + + self._logger.debug(__name__, f"Added client: {g.id}") + except Exception as e: + self._logger.error(__name__, f"Cannot get client", e) + + results = self._servers.get_servers() + if results is None or len(results) == 0: + self._logger.error(__name__, f"Table Servers is empty!") + + def _check_users(self): + self._logger.debug(__name__, f"Start checking Users table") + for g in self._bot.guilds: + g: discord.Guild = g + + try: + server = self._servers.find_server_by_discord_id(g.id) + if server is None: + self._logger.fatal(__name__, f"Server not found in database: {g.id}") + + for u in g.members: + u: Union[discord.Member, discord.User] = u + if u.bot: + self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot") + continue + + user = self._users.find_user_by_discord_id_and_server_id(u.id, server.id) + if user is not None: + continue + + 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._db_context.save_changes() + + self._logger.debug(__name__, f"Added User: {u.id}") + except Exception as e: + self._logger.error(__name__, f"Cannot get User", e) + + results = self._users.get_users() + if results is None or len(results) == 0: + self._logger.error(__name__, f"Table Users is empty!") + + def _check_user_joins(self): + self._logger.debug(__name__, f"Start checking UserJoinedServers table") + for guild in self._bot.guilds: + guild: discord.Guild = guild + + server = self._servers.find_server_by_discord_id(guild.id) + if server is None: + self._logger.fatal(__name__, f"Server not found in database: {guild.id}") + + try: + for u in guild.members: + u: discord.User = u + if u.bot: + self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot") + continue + + user = self._users.find_user_by_discord_id_and_server_id(u.id, server.id) + if user is None: + self._logger.fatal(__name__, f"User not found in database: {u.id}") + + join = self._user_joins.find_active_user_joined_server_by_user_id(user.id) + if join is not None: + continue + + m: discord.Member = u + self._logger.warn( + __name__, + f"Active UserJoinedServer not found in database: {guild.id}:{u.id}@{m.joined_at}", + ) + self._logger.debug( + __name__, + f"Add UserJoinedServer: {guild.id}:{u.id}@{m.joined_at}", + ) + self._user_joins.add_user_joined_server( + UserJoinedServer(user, self._dtp.transform(m.joined_at), None) + ) + self._db_context.save_changes() + + self._logger.debug(__name__, f"Added UserJoinedServer: {u.id}") + except Exception as e: + self._logger.error(__name__, f"Cannot get UserJoinedServer", e) + + results = self._users.get_users() + if results is None or len(results) == 0: + self._logger.error(__name__, f"Table Users is empty!") + + joins = self._user_joins.get_user_joined_servers() + for join in joins: + join: UserJoinedServer = join + if join.user.server.discord_id != guild.id: + continue + + if join.leaved_on is not None: + continue + + dc_user = guild.get_member(join.user.discord_id) + if dc_user is None: + self._logger.warn( + __name__, + f"User {join.user.discord_id} already left the server.", + ) + join.leaved_on = datetime.now() + self._user_joins.update_user_joined_server(join) + + self._db_context.save_changes() + + def _check_user_joins_vc(self): + 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}") + + server = self._servers.find_server_by_discord_id(guild.id) + if server is None: + self._logger.fatal(__name__, f"Server not found in database: {guild.id}") + + try: + for member in guild.members: + if member.bot: + self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot") + continue + + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) + if user is None: + self._logger.fatal(__name__, f"User not found in database: {member.id}") + + joins = self._user_joins_vc.find_active_user_joined_voice_channels_by_user_id(user.id) + if joins is None or len(joins) == 0: + continue + + for join in joins: + self._logger.warn( + __name__, + f"Active UserJoinedVoiceChannel found in database: {guild.id}:{member.id}@{join.joined_on}", + ) + join.leaved_on = datetime.now() + + if ( + (join.leaved_on - join.joined_on).total_seconds() / 60 / 60 + ) > settings.max_voice_state_hours: + join.leaved_on = join.joined_on + timedelta(hours=settings.max_voice_state_hours) + + self._user_joins_vc.update_user_joined_voice_channel(join) + + if self._is_for_shutdown: + user.xp = round(join.time * settings.xp_per_ontime_hour) + self._users.update_user(user) + + self._db_context.save_changes() + + for member in guild.members: + if member.bot: + self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot") + continue + + if member.voice is None or member.voice.channel.id in settings.afk_channel_ids: + continue + + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) + if user is None: + self._logger.fatal(__name__, f"User not found in database: {member.id}") + + join = UserJoinedVoiceChannel(user, member.voice.channel.id, datetime.now()) + self._user_joins_vc.add_user_joined_voice_channel(join) + self._db_context.save_changes() + self._logger.warn(__name__, f"VS {member.voice}") + + except Exception as e: + self._logger.error(__name__, f"Cannot get UserJoinedVoiceChannel", e) + + def _check_user_joined_gs(self): + self._logger.debug(__name__, f"Start checking UserJoinedGameServer table") + for guild in self._bot.guilds: + guild: discord.Guild = guild + + server = self._servers.find_server_by_discord_id(guild.id) + if server is None: + self._logger.fatal(__name__, f"Server not found in database: {guild.id}") + + try: + for member in guild.members: + if member.bot: + self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot") + continue + + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) + if user is None: + self._logger.fatal(__name__, f"User not found in database: {member.id}") + + joins = self._user_joined_gs.find_active_user_joined_game_servers_by_user_id(user.id) + if joins is None or len(joins) == 0: + continue + + for join in joins: + self._logger.warn( + __name__, + 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}") + + if ( + (join.leaved_on - join.joined_on).total_seconds() / 60 / 60 + ) > settings.max_voice_state_hours: + join.leaved_on = join.joined_on + timedelta(hours=settings.max_voice_state_hours) + + self._user_joined_gs.update_user_joined_game_server(join) + if self._is_for_shutdown: + user.xp = round(join.time * settings.xp_per_ontime_hour) + self._users.update_user(user) + + self._db_context.save_changes() + except Exception as e: + self._logger.error(__name__, f"Cannot get UserJoinedGameServer", e) + + def check_data_integrity(self, is_for_shutdown=False): + if is_for_shutdown != self._is_for_shutdown: + self._is_for_shutdown = is_for_shutdown + + self._check_known_users() + self._check_servers() + self._check_clients() + self._check_users() + self._check_user_joins() + self._check_user_joins_vc() + self._check_user_joined_gs() diff --git a/kdb-bot/src/modules/database/database_on_ready_event.py b/kdb-bot/src/modules/database/database_on_ready_event.py index 8d512035..d895592d 100644 --- a/kdb-bot/src/modules/database/database_on_ready_event.py +++ b/kdb-bot/src/modules/database/database_on_ready_event.py @@ -1,31 +1,11 @@ -from ctypes import Union -from datetime import datetime, timedelta +from datetime import datetime -import discord from cpl_core.configuration import ConfigurationABC -from cpl_core.database.context import DatabaseContextABC from cpl_discord.events import OnReadyABC -from cpl_discord.service import DiscordBotServiceABC from bot_core.logging.database_logger import DatabaseLogger -from bot_core.pipes.date_time_offset_pipe import DateTimeOffsetPipe -from bot_data.abc.client_repository_abc import ClientRepositoryABC -from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC -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, -) -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.user import User -from bot_data.model.user_joined_server import UserJoinedServer -from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel +from bot_core.service.data_integrity_service import DataIntegrityService from bot_data.service.seeder_service import SeederService -from bot_data.service.user_repository_service import ServerRepositoryABC -from modules.base.configuration.base_server_settings import BaseServerSettings class DatabaseOnReadyEvent(OnReadyABC): @@ -34,31 +14,13 @@ class DatabaseOnReadyEvent(OnReadyABC): config: ConfigurationABC, logger: DatabaseLogger, seeder: SeederService, - bot: DiscordBotServiceABC, - db_context: DatabaseContextABC, - server_repo: ServerRepositoryABC, - user_repo: UserRepositoryABC, - client_repo: ClientRepositoryABC, - known_users: KnownUserRepositoryABC, - user_joins: UserJoinedServerRepositoryABC, - user_joins_vc: UserJoinedVoiceChannelRepositoryABC, - user_joined_gs: UserJoinedGameServerRepositoryABC, - dtp: DateTimeOffsetPipe, + data_integrity: DataIntegrityService, ): self._config = config self._logger = logger self._seeder = seeder - self._bot = bot - self._db_context = db_context - self._servers = server_repo - self._users = user_repo - self._clients = client_repo - self._known_users = known_users - self._user_joins = user_joins - self._user_joins_vc = user_joins_vc - self._user_joined_gs = user_joined_gs - self._dtp = dtp + self._data_integrity = data_integrity OnReadyABC.__init__(self) self._logger.info(__name__, f"Module {type(self)} loaded") @@ -83,306 +45,10 @@ class DatabaseOnReadyEvent(OnReadyABC): self._logger.error(__name__, "Database init time calculation failed", e) return - def _check_known_users(self): - self._logger.debug(__name__, f"Start checking KnownUsers table, {len(self._bot.users)}") - for u in self._bot.users: - u: discord.User = u - try: - if u.bot: - self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot") - continue - - user = self._known_users.find_user_by_discord_id(u.id) - if user is not None: - continue - - self._logger.warn(__name__, f"Unknown user: {u.id}") - self._logger.debug(__name__, f"Add user: {u.id}") - self._known_users.add_user(KnownUser(u.id)) - self._db_context.save_changes() - - user = self._known_users.find_user_by_discord_id(u.id) - if user is None: - self._logger.fatal(__name__, f"Cannot add user: {u.id}") - - self._logger.debug(__name__, f"Added user: {u.id}") - except Exception as e: - self._logger.error(__name__, f"Cannot get user", e) - - def _check_servers(self): - self._logger.debug(__name__, f"Start checking Servers table") - for g in self._bot.guilds: - g: discord.Guild = g - try: - server = self._servers.find_server_by_discord_id(g.id) - if server is not None: - continue - - self._logger.warn(__name__, f"Server not found in database: {g.id}") - self._logger.debug(__name__, f"Add server: {g.id}") - self._servers.add_server(Server(g.id)) - self._db_context.save_changes() - - server = self._servers.find_server_by_discord_id(g.id) - if server is None: - self._logger.fatal(__name__, f"Cannot add server: {g.id}") - - self._logger.debug(__name__, f"Added server: {g.id}") - except Exception as e: - self._logger.error(__name__, f"Cannot get server", e) - - results = self._servers.get_servers() - if results is None or len(results) == 0: - self._logger.error(__name__, f"Table Servers is empty!") - - def _check_clients(self): - self._logger.debug(__name__, f"Start checking Clients table") - for g in self._bot.guilds: - g: discord.Guild = g - try: - server: Server = self._servers.find_server_by_discord_id(g.id) - if server is None: - self._logger.fatal(__name__, f"Server not found in database: {g.id}") - - client = self._clients.find_client_by_server_id(server.id) - if client is not None: - continue - - self._logger.warn( - __name__, - f"Client for server {g.id} not found in database: {self._bot.user.id}", - ) - self._logger.debug(__name__, f"Add client: {self._bot.user.id}") - self._clients.add_client(Client(self._bot.user.id, 0, 0, 0, 0, 0, server)) - self._db_context.save_changes() - - client = self._clients.find_client_by_server_id(server.id) - if client is None: - self._logger.fatal( - __name__, - f"Cannot add client {self._bot.user.id} for server {g.id}", - ) - - self._logger.debug(__name__, f"Added client: {g.id}") - except Exception as e: - self._logger.error(__name__, f"Cannot get client", e) - - results = self._servers.get_servers() - if results is None or len(results) == 0: - self._logger.error(__name__, f"Table Servers is empty!") - - def _check_users(self): - self._logger.debug(__name__, f"Start checking Users table") - for g in self._bot.guilds: - g: discord.Guild = g - - try: - server = self._servers.find_server_by_discord_id(g.id) - if server is None: - self._logger.fatal(__name__, f"Server not found in database: {g.id}") - - for u in g.members: - u: Union[discord.Member, discord.User] = u - if u.bot: - self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot") - continue - - user = self._users.find_user_by_discord_id_and_server_id(u.id, server.id) - if user is not None: - continue - - 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._db_context.save_changes() - - self._logger.debug(__name__, f"Added User: {u.id}") - except Exception as e: - self._logger.error(__name__, f"Cannot get User", e) - - results = self._users.get_users() - if results is None or len(results) == 0: - self._logger.error(__name__, f"Table Users is empty!") - - def _check_user_joins(self): - self._logger.debug(__name__, f"Start checking UserJoinedServers table") - for guild in self._bot.guilds: - guild: discord.Guild = guild - - server = self._servers.find_server_by_discord_id(guild.id) - if server is None: - self._logger.fatal(__name__, f"Server not found in database: {guild.id}") - - try: - for u in guild.members: - u: discord.User = u - if u.bot: - self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot") - continue - - user = self._users.find_user_by_discord_id_and_server_id(u.id, server.id) - if user is None: - self._logger.fatal(__name__, f"User not found in database: {u.id}") - - join = self._user_joins.find_active_user_joined_server_by_user_id(user.id) - if join is not None: - continue - - m: discord.Member = u - self._logger.warn( - __name__, - f"Active UserJoinedServer not found in database: {guild.id}:{u.id}@{m.joined_at}", - ) - self._logger.debug( - __name__, - f"Add UserJoinedServer: {guild.id}:{u.id}@{m.joined_at}", - ) - self._user_joins.add_user_joined_server( - UserJoinedServer(user, self._dtp.transform(m.joined_at), None) - ) - self._db_context.save_changes() - - self._logger.debug(__name__, f"Added UserJoinedServer: {u.id}") - except Exception as e: - self._logger.error(__name__, f"Cannot get UserJoinedServer", e) - - results = self._users.get_users() - if results is None or len(results) == 0: - self._logger.error(__name__, f"Table Users is empty!") - - joins = self._user_joins.get_user_joined_servers() - for join in joins: - join: UserJoinedServer = join - if join.user.server.discord_id != guild.id: - continue - - if join.leaved_on is not None: - continue - - dc_user = guild.get_member(join.user.discord_id) - if dc_user is None: - self._logger.warn( - __name__, - f"User {join.user.discord_id} already left the server.", - ) - join.leaved_on = datetime.now() - self._user_joins.update_user_joined_server(join) - - self._db_context.save_changes() - - def _check_user_joins_vc(self): - 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}") - - server = self._servers.find_server_by_discord_id(guild.id) - if server is None: - self._logger.fatal(__name__, f"Server not found in database: {guild.id}") - - try: - for member in guild.members: - if member.bot: - self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot") - continue - - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) - if user is None: - self._logger.fatal(__name__, f"User not found in database: {member.id}") - - joins = self._user_joins_vc.find_active_user_joined_voice_channels_by_user_id(user.id) - if joins is None or len(joins) == 0: - continue - - for join in joins: - self._logger.warn( - __name__, - f"Active UserJoinedVoiceChannel found in database: {guild.id}:{member.id}@{join.joined_on}", - ) - join.leaved_on = datetime.now() - - if ( - (join.leaved_on - join.joined_on).total_seconds() / 60 / 60 - ) > settings.max_voice_state_hours: - join.leaved_on = join.joined_on + timedelta(hours=settings.max_voice_state_hours) - - self._user_joins_vc.update_user_joined_voice_channel(join) - # todo: maybe add XP - self._db_context.save_changes() - - for member in guild.members: - if member.bot: - self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot") - continue - - if member.voice is None or member.voice.channel.id in settings.afk_channel_ids: - continue - - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) - if user is None: - self._logger.fatal(__name__, f"User not found in database: {member.id}") - - join = UserJoinedVoiceChannel(user, member.voice.channel.id, datetime.now()) - self._user_joins_vc.add_user_joined_voice_channel(join) - self._db_context.save_changes() - self._logger.warn(__name__, f"VS {member.voice}") - - except Exception as e: - self._logger.error(__name__, f"Cannot get UserJoinedVoiceChannel", e) - - def _check_user_joined_gs(self): - self._logger.debug(__name__, f"Start checking UserJoinedGameServer table") - for guild in self._bot.guilds: - guild: discord.Guild = guild - - server = self._servers.find_server_by_discord_id(guild.id) - if server is None: - self._logger.fatal(__name__, f"Server not found in database: {guild.id}") - - try: - for member in guild.members: - if member.bot: - self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot") - continue - - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) - if user is None: - self._logger.fatal(__name__, f"User not found in database: {member.id}") - - joins = self._user_joined_gs.find_active_user_joined_game_servers_by_user_id(user.id) - if joins is None or len(joins) == 0: - continue - - for join in joins: - self._logger.warn( - __name__, - 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}") - - if ( - (join.leaved_on - join.joined_on).total_seconds() / 60 / 60 - ) > settings.max_voice_state_hours: - join.leaved_on = join.joined_on + timedelta(hours=settings.max_voice_state_hours) - - self._user_joined_gs.update_user_joined_game_server(join) - # todo: maybe add XP - self._db_context.save_changes() - except Exception as e: - self._logger.error(__name__, f"Cannot get UserJoinedGameServer", e) - async def on_ready(self): self._logger.debug(__name__, f"Module {type(self)} started") - self._check_known_users() - self._check_servers() - self._check_clients() - self._check_users() - self._check_user_joins() - self._check_user_joins_vc() - self._check_user_joined_gs() - + self._data_integrity.check_data_integrity() await self._seeder.seed() self._validate_init_time() -- 2.45.2 From f034413e35e53affb77f57c701e18a32e3c207c8 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 14 Jun 2023 09:29:07 +0200 Subject: [PATCH 010/127] Added data integrity check to shutdown #292_shutdown_procedure --- kdb-bot/src/bot/application.py | 3 +++ kdb-bot/src/bot_core/service/data_integrity_service.py | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/kdb-bot/src/bot/application.py b/kdb-bot/src/bot/application.py index 4198de6b..dcedeb08 100644 --- a/kdb-bot/src/bot/application.py +++ b/kdb-bot/src/bot/application.py @@ -10,6 +10,7 @@ from cpl_translation import TranslatePipe, TranslationServiceABC, TranslationSet from bot_api.api_thread import ApiThread from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings +from bot_core.service.data_integrity_service import DataIntegrityService class Application(DiscordBotApplicationABC): @@ -21,6 +22,7 @@ class Application(DiscordBotApplicationABC): # cpl-core self._logger: LoggerABC = services.get_service(LoggerABC) + self._data_integrity: DataIntegrityService = services.get_service(DataIntegrityService) # cpl-discord self._bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC) self._bot_settings: DiscordBotSettings = config.get_configuration(DiscordBotSettings) @@ -68,6 +70,7 @@ class Application(DiscordBotApplicationABC): if self._feature_flags.get_flag(FeatureFlagsEnum.api_module): self._api.stop() + self._data_integrity.check_data_integrity(is_for_shutdown=True) await self._bot.close() self._logger.info(__name__, f"Stopped {DiscordBotService.__name__}") except Exception as e: 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 849d5261..e00028c8 100644 --- a/kdb-bot/src/bot_core/service/data_integrity_service.py +++ b/kdb-bot/src/bot_core/service/data_integrity_service.py @@ -307,7 +307,6 @@ class DataIntegrityService: join = UserJoinedVoiceChannel(user, member.voice.channel.id, datetime.now()) self._user_joins_vc.add_user_joined_voice_channel(join) self._db_context.save_changes() - self._logger.warn(__name__, f"VS {member.voice}") except Exception as e: self._logger.error(__name__, f"Cannot get UserJoinedVoiceChannel", e) -- 2.45.2 From 00db6ac10fbd34c2f1745b65fad73a6fd69360b9 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 14 Jun 2023 09:34:31 +0200 Subject: [PATCH 011/127] Improved open voice state check #292_shutdown_procedure --- kdb-bot/src/bot_core/service/data_integrity_service.py | 4 ++++ 1 file changed, 4 insertions(+) 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 e00028c8..c3f76912 100644 --- a/kdb-bot/src/bot_core/service/data_integrity_service.py +++ b/kdb-bot/src/bot_core/service/data_integrity_service.py @@ -259,6 +259,7 @@ class DataIntegrityService: self._logger.fatal(__name__, f"Server not found in database: {guild.id}") try: + # close open voice states for member in guild.members: if member.bot: self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot") @@ -291,7 +292,10 @@ class DataIntegrityService: self._users.update_user(user) self._db_context.save_changes() + if self._is_for_shutdown: + return + # add open voice states for member in guild.members: if member.bot: self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot") -- 2.45.2 From 607b7d8aee4a584a2f6e8594137a8a4e733f344c Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 14 Jun 2023 11:48:49 +0200 Subject: [PATCH 012/127] Ensure bot shutdown before data checks #292_shutdown_procedure --- kdb-bot/src/bot/application.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kdb-bot/src/bot/application.py b/kdb-bot/src/bot/application.py index dcedeb08..ca3e0976 100644 --- a/kdb-bot/src/bot/application.py +++ b/kdb-bot/src/bot/application.py @@ -70,8 +70,8 @@ class Application(DiscordBotApplicationABC): if self._feature_flags.get_flag(FeatureFlagsEnum.api_module): self._api.stop() - self._data_integrity.check_data_integrity(is_for_shutdown=True) await self._bot.close() + self._data_integrity.check_data_integrity(is_for_shutdown=True) self._logger.info(__name__, f"Stopped {DiscordBotService.__name__}") except Exception as e: self._logger.error(__name__, "stop failed", e) @@ -79,4 +79,4 @@ class Application(DiscordBotApplicationABC): Console.write_line() def is_restart(self): - return True if self._configuration.get_configuration("IS_RESTART") == "true" else False # + return True if self._configuration.get_configuration("IS_RESTART") == "true" else False -- 2.45.2 From 2c9569b75f84e4c9b646ed7bd157098c6c98499a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 18 Jun 2023 18:51:36 +0200 Subject: [PATCH 013/127] Fixed gql playground # --- kdb-bot/src/bot_api/controller/graphql_controller.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kdb-bot/src/bot_api/controller/graphql_controller.py b/kdb-bot/src/bot_api/controller/graphql_controller.py index aefd8f13..fda337d5 100644 --- a/kdb-bot/src/bot_api/controller/graphql_controller.py +++ b/kdb-bot/src/bot_api/controller/graphql_controller.py @@ -1,5 +1,5 @@ from ariadne import graphql_sync -from ariadne.explorer import ExplorerGraphiQL +from ariadne.explorer import ExplorerPlayground from cpl_core.configuration import ConfigurationABC from cpl_core.environment import ApplicationEnvironmentABC from flask import request, jsonify @@ -30,7 +30,7 @@ class GraphQLController: if self._env.environment_name != "development": return "", 403 - return ExplorerGraphiQL().html(None), 200 + return ExplorerPlayground().html(None), 200 @Route.post(f"{BasePath}") @Route.authorize(by_api_key=True) -- 2.45.2 From 7f197a0ea780f0cae359a430c42610abc8742feb Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 14 Jun 2023 19:30:30 +0200 Subject: [PATCH 014/127] Added achievement data model #268_achievements --- kdb-bot/cpl-workspace.json | 10 +- kdb-bot/src/bot/module_list.py | 2 + .../src/bot/startup_migration_extension.py | 2 + .../configuration/feature_flags_enum.py | 1 + .../configuration/feature_flags_settings.py | 1 + .../abc/achievement_repository_abc.py | 35 ++++++ kdb-bot/src/bot_data/data_module.py | 3 + .../migration/achievements_migration.py | 95 ++++++++++++++ kdb-bot/src/bot_data/model/achievement.py | 117 ++++++++++++++++++ .../src/bot_data/model/achievement_history.py | 66 ++++++++++ .../achievements_repository_service.py | 72 +++++++++++ kdb-bot/src/modules/achievements/__init__.py | 1 + .../modules/achievements/achievements.json | 44 +++++++ .../achievements/achievements_module.py | 18 +++ 14 files changed, 459 insertions(+), 8 deletions(-) create mode 100644 kdb-bot/src/bot_data/abc/achievement_repository_abc.py create mode 100644 kdb-bot/src/bot_data/migration/achievements_migration.py create mode 100644 kdb-bot/src/bot_data/model/achievement.py create mode 100644 kdb-bot/src/bot_data/model/achievement_history.py create mode 100644 kdb-bot/src/bot_data/service/achievements_repository_service.py create mode 100644 kdb-bot/src/modules/achievements/__init__.py create mode 100644 kdb-bot/src/modules/achievements/achievements.json create mode 100644 kdb-bot/src/modules/achievements/achievements_module.py diff --git a/kdb-bot/cpl-workspace.json b/kdb-bot/cpl-workspace.json index 90d77e00..1e44549f 100644 --- a/kdb-bot/cpl-workspace.json +++ b/kdb-bot/cpl-workspace.json @@ -17,29 +17,23 @@ "checks": "tools/checks/checks.json", "get-version": "tools/get_version/get-version.json", "post-build": "tools/post_build/post-build.json", - "set-version": "tools/set_version/set-version.json" + "set-version": "tools/set_version/set-version.json", + "modules/achievements": "src/modules/achievements/modules/achievements.json" }, "Scripts": { "format": "black ./", - "sv": "cpl set-version $ARGS", "set-version": "cpl run set-version $ARGS --dev; echo '';", - "gv": "cpl get-version", "get-version": "export VERSION=$(cpl run get-version --dev); echo $VERSION;", - "pre-build": "cpl set-version $ARGS; black ./;", "post-build": "cpl run post-build --dev; black ./;", - "pre-prod": "cpl build", "prod": "export KDB_ENVIRONMENT=production; export KDB_NAME=KDB-Prod; cpl start;", - "pre-stage": "cpl build", "stage": "export KDB_ENVIRONMENT=staging; export KDB_NAME=KDB-Stage; cpl start;", - "pre-dev": "cpl build", "dev": "export KDB_ENVIRONMENT=development; export KDB_NAME=KDB-Dev; cpl start;", - "docker-build": "cpl build $ARGS; docker build -t kdb-bot/kdb-bot:$(cpl gv) .;", "dc-up": "docker-compose up -d", "dc-down": "docker-compose down", diff --git a/kdb-bot/src/bot/module_list.py b/kdb-bot/src/bot/module_list.py index 700f0c73..7c6fb418 100644 --- a/kdb-bot/src/bot/module_list.py +++ b/kdb-bot/src/bot/module_list.py @@ -5,6 +5,7 @@ from bot_core.core_extension.core_extension_module import CoreExtensionModule from bot_core.core_module import CoreModule from bot_data.data_module import DataModule from bot_graphql.graphql_module import GraphQLModule +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 @@ -31,6 +32,7 @@ class ModuleList: LevelModule, ApiModule, TechnicianModule, + AchievementsModule, # has to be last! BootLogModule, CoreExtensionModule, diff --git a/kdb-bot/src/bot/startup_migration_extension.py b/kdb-bot/src/bot/startup_migration_extension.py index 5eba461b..a2d639fa 100644 --- a/kdb-bot/src/bot/startup_migration_extension.py +++ b/kdb-bot/src/bot/startup_migration_extension.py @@ -4,6 +4,7 @@ from cpl_core.dependency_injection import ServiceCollectionABC from cpl_core.environment import ApplicationEnvironmentABC from bot_data.abc.migration_abc import MigrationABC +from bot_data.migration.achievements_migration import AchievementsMigration 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 @@ -42,3 +43,4 @@ class StartupMigrationExtension(StartupExtensionABC): services.add_transient(MigrationABC, RemoveStatsMigration) # 19.02.2023 #190 - 1.0.0 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 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 aeb18a99..37a579fe 100644 --- a/kdb-bot/src/bot_core/configuration/feature_flags_enum.py +++ b/kdb-bot/src/bot_core/configuration/feature_flags_enum.py @@ -3,6 +3,7 @@ from enum import Enum class FeatureFlagsEnum(Enum): # modules + achievements_module = "AchievementsModule" api_module = "ApiModule" admin_module = "AdminModule" auto_role_module = "AutoRoleModule" 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 777e256b..b0d297b8 100644 --- a/kdb-bot/src/bot_core/configuration/feature_flags_settings.py +++ b/kdb-bot/src/bot_core/configuration/feature_flags_settings.py @@ -12,6 +12,7 @@ class FeatureFlagsSettings(ConfigurationModelABC): 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 diff --git a/kdb-bot/src/bot_data/abc/achievement_repository_abc.py b/kdb-bot/src/bot_data/abc/achievement_repository_abc.py new file mode 100644 index 00000000..4b817759 --- /dev/null +++ b/kdb-bot/src/bot_data/abc/achievement_repository_abc.py @@ -0,0 +1,35 @@ +from abc import ABC, abstractmethod + +from cpl_query.extension import List + +from bot_data.model.achievement import Achievement + + +class AchievementRepositoryABC(ABC): + @abstractmethod + def __init__(self): + pass + + @abstractmethod + def get_achievements(self) -> List[Achievement]: + pass + + @abstractmethod + def get_achievement_by_id(self, id: int) -> Achievement: + pass + + @abstractmethod + def get_achievements_by_server_id(self, server_id: int) -> List[Achievement]: + pass + + @abstractmethod + def add_achievement(self, achievement: Achievement): + pass + + @abstractmethod + def update_achievement(self, achievement: Achievement): + pass + + @abstractmethod + def delete_achievement(self, achievement: Achievement): + pass diff --git a/kdb-bot/src/bot_data/data_module.py b/kdb-bot/src/bot_data/data_module.py index 899151d6..fd571abb 100644 --- a/kdb-bot/src/bot_data/data_module.py +++ b/kdb-bot/src/bot_data/data_module.py @@ -5,6 +5,7 @@ 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.achievement_repository_abc import AchievementRepositoryABC 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 @@ -24,6 +25,7 @@ from bot_data.abc.user_message_count_per_hour_repository_abc import ( ) from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC +from bot_data.service.achievements_repository_service import AchievementRepositoryService from bot_data.service.api_key_repository_service import ApiKeyRepositoryService from bot_data.service.auth_user_repository_service import AuthUserRepositoryService from bot_data.service.auto_role_repository_service import AutoRoleRepositoryService @@ -77,5 +79,6 @@ class DataModule(ModuleABC): ) services.add_transient(GameServerRepositoryABC, GameServerRepositoryService) services.add_transient(UserGameIdentRepositoryABC, UserGameIdentRepositoryService) + services.add_transient(AchievementRepositoryABC, AchievementRepositoryService) services.add_transient(SeederService) diff --git a/kdb-bot/src/bot_data/migration/achievements_migration.py b/kdb-bot/src/bot_data/migration/achievements_migration.py new file mode 100644 index 00000000..8c310526 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/achievements_migration.py @@ -0,0 +1,95 @@ +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.migration_abc import MigrationABC +from bot_data.db_context import DBContext + + +class AchievementsMigration(MigrationABC): + name = "1.1.0_AchievementsMigration" + + 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 `Achievements` ( + `Id` BIGINT NOT NULL AUTO_INCREMENT, + `ServerId` BIGINT, + `Name` VARCHAR(255) NOT NULL, + `Attribute` VARCHAR(255) NOT NULL, + `Operator` VARCHAR(2) NOT NULL, + `Value` 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`), + FOREIGN KEY (`ServerId`) REFERENCES `Servers`(`ServerId`) + ); + """ + ) + ) + + self._cursor.execute( + str( + f""" + ALTER TABLE Users ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP; + ALTER TABLE Users ADD ReactionCount BIGINT NOT NULL DEFAULT 0 AFTER XP; + """ + ) + ) + + self._cursor.execute( + str( + f""" + ALTER TABLE UsersHistory ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP; + ALTER TABLE UsersHistory ADD ReactionCount BIGINT NOT NULL DEFAULT 0 AFTER XP; + """ + ) + ) + + self._cursor.execute( + str( + f""" + DROP TRIGGER IF EXISTS `TR_AchievementsUpdate`; + + CREATE TRIGGER `TR_AchievementsUpdate` + AFTER UPDATE + ON `Achievements` + FOR EACH ROW + BEGIN + INSERT INTO `AchievementsHistory` ( + `Id`, `Name`, `Attribute`, `Operator`, `Value`, `ServerId`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.Name, OLD.Attribute, OLD.Operator, OLD.Value, OLD.ServerId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); + END; + + DROP TRIGGER IF EXISTS `TR_AchievementsDelete`; + + CREATE TRIGGER `TR_AchievementsDelete` + AFTER DELETE + ON `Achievements` + FOR EACH ROW + BEGIN + INSERT INTO `AchievementsHistory` ( + `Id`, `Name`, `Attribute`, `Operator`, `Value`, `ServerId`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.Name, OLD.Attribute, OLD.Operator, OLD.Value, OLD.ServerId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); + END; + """ + ) + ) + + def downgrade(self): + self._cursor.execute("DROP TABLE `Achievements`;") + + self._cursor.execute(str(f"""ALTER TABLE Users DROP COLUMN MessageCount;""")) + self._cursor.execute(str(f"""ALTER TABLE Users DROP COLUMN ReactionCount;""")) diff --git a/kdb-bot/src/bot_data/model/achievement.py b/kdb-bot/src/bot_data/model/achievement.py new file mode 100644 index 00000000..b9a44089 --- /dev/null +++ b/kdb-bot/src/bot_data/model/achievement.py @@ -0,0 +1,117 @@ +from datetime import datetime +from typing import Optional + +from cpl_core.database import TableABC + +from bot_data.model.server import Server + + +class Achievement(TableABC): + def __init__( + self, + name: str, + attribute: str, + operator: str, + value: str, + server: Optional[Server], + created_at: datetime = None, + modified_at: datetime = None, + id=0, + ): + self._id = id + self._name = name + self._attribute = attribute + self._operator = operator + self._value = value + self._server = server + + 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 name(self) -> str: + return self._name + + @name.setter + def name(self, value: str): + self._name = value + + @property + def operator(self) -> str: + return self._operator + + @operator.setter + def operator(self, value: str): + self._operator = value + + @property + def value(self) -> str: + return self._value + + @value.setter + def value(self, value: str): + self._value = value + + @property + def server(self) -> Server: + return self._server + + @staticmethod + def get_select_all_string() -> str: + return str( + f""" + SELECT * FROM `Achievements`; + """ + ) + + @staticmethod + def get_select_by_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `Achievements` + WHERE `Id` = {id}; + """ + ) + + @property + def insert_string(self) -> str: + return str( + f""" + INSERT INTO `Achievements` ( + `Name`, `Attribute`, `Operator`, `Value`, `ServerId` + ) VALUES ( + '{self._name}', + '{self._attribute}', + '{self._operator}', + '{self._value}', + {self._server.id} + ); + """ + ) + + @property + def udpate_string(self) -> str: + return str( + f""" + UPDATE `Levels` + SET `Name` = '{self._name}', + `Attribute` = '{self._attribute}', + `Operator` = '{self._operator}', + `Value` = '{self._value}' + WHERE `Id` = {self._id}; + """ + ) + + @property + def delete_string(self) -> str: + return str( + f""" + DELETE FROM `Achievements` + WHERE `Id` = {self._id}; + """ + ) diff --git a/kdb-bot/src/bot_data/model/achievement_history.py b/kdb-bot/src/bot_data/model/achievement_history.py new file mode 100644 index 00000000..74208075 --- /dev/null +++ b/kdb-bot/src/bot_data/model/achievement_history.py @@ -0,0 +1,66 @@ +from datetime import datetime +from typing import Optional + +from cpl_core.database import TableABC + +from bot_data.abc.history_table_abc import HistoryTableABC +from bot_data.model.server import Server + + +class Achievement(HistoryTableABC): + def __init__( + self, + name: str, + attribute: str, + operator: str, + value: str, + server: Optional[Server], + deleted: bool, + date_from: str, + date_to: str, + id=0, + ): + HistoryTableABC.__init__(self) + + self._id = id + self._name = name + self._attribute = attribute + self._operator = operator + self._value = value + self._server = server + + self._deleted = deleted + self._date_from = date_from + self._date_to = date_to + + @property + def id(self) -> int: + return self._id + + @property + def name(self) -> str: + return self._name + + @name.setter + def name(self, value: str): + self._name = value + + @property + def operator(self) -> str: + return self._operator + + @operator.setter + def operator(self, value: str): + self._operator = value + + @property + def value(self) -> str: + return self._value + + @value.setter + def value(self, value: str): + self._value = value + + @property + def server(self) -> Server: + return self._server diff --git a/kdb-bot/src/bot_data/service/achievements_repository_service.py b/kdb-bot/src/bot_data/service/achievements_repository_service.py new file mode 100644 index 00000000..d910a6c2 --- /dev/null +++ b/kdb-bot/src/bot_data/service/achievements_repository_service.py @@ -0,0 +1,72 @@ +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.achievement_repository_abc import AchievementRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.model.achievement import Achievement + + +class AchievementRepositoryService(AchievementRepositoryABC): + def __init__( + self, + logger: DatabaseLogger, + db_context: DatabaseContextABC, + servers: ServerRepositoryABC, + ): + self._logger = logger + self._context = db_context + + self._servers = servers + + AchievementRepositoryABC.__init__(self) + + def _from_result(self, result: tuple): + return Achievement( + result[3], + result[4], + result[5], + result[6], + self._servers.get_server_by_id(result[2]), + result[6], + result[7], + id=result[0], + ) + + def get_achievements(self) -> List[Achievement]: + achievements = List(Achievement) + self._logger.trace(__name__, f"Send SQL command: {Achievement.get_select_all_string()}") + results = self._context.select(Achievement.get_select_all_string()) + for result in results: + self._logger.trace(__name__, f"Get user with id {result[0]}") + achievements.append(self._from_result(result)) + + return achievements + + def get_achievement_by_id(self, id: int) -> Achievement: + self._logger.trace(__name__, f"Send SQL command: {Achievement.get_select_by_id_string(id)}") + result = self._context.select(Achievement.get_select_by_id_string(id))[0] + + return self._from_result(result) + + def get_achievements_by_server_id(self, server_id: int) -> List[Achievement]: + achievements = List(Achievement) + self._logger.trace(__name__, f"Send SQL command: {Achievement.get_select_by_id_string(server_id)}") + results = self._context.select(Achievement.get_select_all_string()) + for result in results: + self._logger.trace(__name__, f"Get user with id {result[0]}") + achievements.append(self._from_result(result)) + + return achievements + + def add_achievement(self, achievement: Achievement): + self._logger.trace(__name__, f"Send SQL command: {achievement.insert_string}") + self._context.cursor.execute(achievement.insert_string) + + def update_achievement(self, achievement: Achievement): + self._logger.trace(__name__, f"Send SQL command: {achievement.udpate_string}") + self._context.cursor.execute(achievement.udpate_string) + + def delete_achievement(self, achievement: Achievement): + self._logger.trace(__name__, f"Send SQL command: {achievement.delete_string}") + self._context.cursor.execute(achievement.delete_string) diff --git a/kdb-bot/src/modules/achievements/__init__.py b/kdb-bot/src/modules/achievements/__init__.py new file mode 100644 index 00000000..425ab6c1 --- /dev/null +++ b/kdb-bot/src/modules/achievements/__init__.py @@ -0,0 +1 @@ +# imports diff --git a/kdb-bot/src/modules/achievements/achievements.json b/kdb-bot/src/modules/achievements/achievements.json new file mode 100644 index 00000000..5937d753 --- /dev/null +++ b/kdb-bot/src/modules/achievements/achievements.json @@ -0,0 +1,44 @@ +{ + "ProjectSettings": { + "Name": "achievements", + "Version": { + "Major": "1", + "Minor": "1", + "Micro": "0" + }, + "Author": "Sven Heidemann", + "AuthorEmail": "sven.heidemann@sh-edraft.de", + "Description": "Keksdose bot - achievements", + "LongDescription": "Discord bot for the Keksdose discord Server - achievements module", + "URL": "https://www.sh-edraft.de", + "CopyrightDate": "2023", + "CopyrightName": "sh-edraft.de", + "LicenseName": "MIT", + "LicenseDescription": "MIT, see LICENSE for more details.", + "Dependencies": [ + "cpl-core>=2023.4.0.post2" + ], + "DevDependencies": [ + "cpl-cli>=2023.4.0.post3" + ], + "PythonVersion": ">=3.10.4", + "PythonPath": {}, + "Classifiers": [] + }, + "BuildSettings": { + "ProjectType": "library", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "achievements.main", + "EntryPoint": "achievements", + "IncludePackageData": false, + "Included": [], + "Excluded": [ + "*/__pycache__", + "*/logs", + "*/tests" + ], + "PackageData": {}, + "ProjectReferences": [] + } +} \ No newline at end of file diff --git a/kdb-bot/src/modules/achievements/achievements_module.py b/kdb-bot/src/modules/achievements/achievements_module.py new file mode 100644 index 00000000..c3a7d5cd --- /dev/null +++ b/kdb-bot/src/modules/achievements/achievements_module.py @@ -0,0 +1,18 @@ +from cpl_core.configuration import ConfigurationABC +from cpl_core.dependency_injection import ServiceCollectionABC +from cpl_core.environment import ApplicationEnvironmentABC +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 + + +class AchievementsModule(ModuleABC): + def __init__(self, dc: DiscordCollectionABC): + ModuleABC.__init__(self, dc, FeatureFlagsEnum.auto_role_module) + + def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC): + pass + + def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): + pass -- 2.45.2 From fdbba1b89c2b46444d65a521733e3700c4263057 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 14 Jun 2023 19:56:38 +0200 Subject: [PATCH 015/127] Fixed models #268_achievements --- .../migration/achievements_migration.py | 29 ++++++++++++------- kdb-bot/src/bot_data/model/user.py | 28 ++++++++++++++++-- .../service/user_repository_service.py | 6 ++-- 3 files changed, 48 insertions(+), 15 deletions(-) diff --git a/kdb-bot/src/bot_data/migration/achievements_migration.py b/kdb-bot/src/bot_data/migration/achievements_migration.py index 8c310526..160d379c 100644 --- a/kdb-bot/src/bot_data/migration/achievements_migration.py +++ b/kdb-bot/src/bot_data/migration/achievements_migration.py @@ -37,20 +37,26 @@ class AchievementsMigration(MigrationABC): self._cursor.execute( str( f""" - ALTER TABLE Users ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP; - ALTER TABLE Users ADD ReactionCount BIGINT NOT NULL DEFAULT 0 AFTER XP; + CREATE TABLE IF NOT EXISTS `AchievementsHistory` + ( + `Id` BIGINT(20) NOT NULL, + `ServerId` BIGINT, + `Name` VARCHAR(255) NOT NULL, + `Attribute` VARCHAR(255) NOT NULL, + `Operator` VARCHAR(2) NOT NULL, + `Value` VARCHAR(255) NOT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL + ); """ ) ) - self._cursor.execute( - str( - f""" - ALTER TABLE UsersHistory ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP; - ALTER TABLE UsersHistory ADD ReactionCount BIGINT NOT NULL DEFAULT 0 AFTER XP; - """ - ) - ) + self._cursor.execute(str(f"""ALTER TABLE Users ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP;""")) + self._cursor.execute(str(f"""ALTER TABLE Users ADD ReactionCount BIGINT NOT NULL DEFAULT 0 AFTER XP;""")) + self._cursor.execute(str(f"""ALTER TABLE UsersHistory ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP;""")) + self._cursor.execute(str(f"""ALTER TABLE UsersHistory ADD ReactionCount BIGINT NOT NULL DEFAULT 0 AFTER XP;""")) self._cursor.execute( str( @@ -85,7 +91,8 @@ class AchievementsMigration(MigrationABC): ); END; """ - ) + ), + multi=True, ) def downgrade(self): diff --git a/kdb-bot/src/bot_data/model/user.py b/kdb-bot/src/bot_data/model/user.py index 7472e689..ff654ae3 100644 --- a/kdb-bot/src/bot_data/model/user.py +++ b/kdb-bot/src/bot_data/model/user.py @@ -15,6 +15,8 @@ class User(TableABC): self, dc_id: int, xp: int, + message_count: int, + reaction_count: int, server: Optional[Server], created_at: datetime = None, modified_at: datetime = None, @@ -23,6 +25,8 @@ class User(TableABC): self._user_id = id self._discord_id = dc_id self._xp = xp + self._message_count = message_count + self._reaction_count = reaction_count self._server = server TableABC.__init__(self) @@ -59,6 +63,22 @@ class User(TableABC): def xp(self, value: int): self._xp = value + @property + def message_count(self) -> int: + return self._message_count + + @message_count.setter + def message_count(self, value: int): + self._message_count = value + + @property + def reaction_count(self) -> int: + return self._reaction_count + + @reaction_count.setter + def reaction_count(self, value: int): + self._reaction_count = value + @property @ServiceProviderABC.inject def ontime(self, services: ServiceProviderABC) -> float: @@ -151,10 +171,12 @@ class User(TableABC): return str( f""" INSERT INTO `Users` ( - `DiscordId`, `XP`, `ServerId` + `DiscordId`, `XP`, `MessageCount`, `ReactionCount`, `ServerId` ) VALUES ( {self._discord_id}, {self._xp}, + {self._message_count}, + {self._reaction_count}, {self._server.id} ); """ @@ -165,7 +187,9 @@ class User(TableABC): return str( f""" UPDATE `Users` - SET `XP` = {self._xp} + SET `XP` = {self._xp}, + `MessageCount` = {self._message_count}, + `ReactionCount` = {self._reaction_count} WHERE `UserId` = {self._user_id}; """ ) diff --git a/kdb-bot/src/bot_data/service/user_repository_service.py b/kdb-bot/src/bot_data/service/user_repository_service.py index adc9685c..73387908 100644 --- a/kdb-bot/src/bot_data/service/user_repository_service.py +++ b/kdb-bot/src/bot_data/service/user_repository_service.py @@ -27,9 +27,11 @@ class UserRepositoryService(UserRepositoryABC): return User( result[1], result[2], - self._servers.get_server_by_id(result[3]), + result[3], result[4], - result[5], + self._servers.get_server_by_id(result[5]), + result[6], + result[7], id=result[0], ) -- 2.45.2 From d6854d44b7b3830b727ec17a1fa99280269046d1 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 11 Jul 2023 18:16:32 +0200 Subject: [PATCH 016/127] Added achievement gql endpoint [UNTESTED] #268_achievements --- .../bot_graphql/filter/achievement_filter.py | 60 +++++++++++++++++++ kdb-bot/src/bot_graphql/graphql_module.py | 6 ++ kdb-bot/src/bot_graphql/model/achievement.gql | 52 ++++++++++++++++ kdb-bot/src/bot_graphql/model/mutation.gql | 1 + kdb-bot/src/bot_graphql/model/query.gql | 3 + kdb-bot/src/bot_graphql/mutation.py | 4 +- .../mutations/achievement_mutation.py | 43 +++++++++++++ .../bot_graphql/queries/achievement_query.py | 19 ++++++ kdb-bot/src/bot_graphql/query.py | 4 ++ kdb-web/package.json | 2 +- kdb-web/src/assets/config.json | 2 +- 11 files changed, 193 insertions(+), 3 deletions(-) create mode 100644 kdb-bot/src/bot_graphql/filter/achievement_filter.py create mode 100644 kdb-bot/src/bot_graphql/model/achievement.gql create mode 100644 kdb-bot/src/bot_graphql/mutations/achievement_mutation.py create mode 100644 kdb-bot/src/bot_graphql/queries/achievement_query.py diff --git a/kdb-bot/src/bot_graphql/filter/achievement_filter.py b/kdb-bot/src/bot_graphql/filter/achievement_filter.py new file mode 100644 index 00000000..49c0eab9 --- /dev/null +++ b/kdb-bot/src/bot_graphql/filter/achievement_filter.py @@ -0,0 +1,60 @@ +from cpl_query.extension import List + +from bot_data.model.user import User +from bot_graphql.abc.filter_abc import FilterABC + + +class AchievementFilter(FilterABC): + def __init__(self): + FilterABC.__init__(self) + + self._id = None + self._name = None + self._attribute = None + self._operator = None + self._value = None + self._server = None + + def from_dict(self, values: dict): + if "id" in values: + self._id = int(values["id"]) + + if "name" in values: + self._name = values["name"] + + if "attribute" in values: + self._attribute = values["attribute"] + + if "operator" in values: + self._operator = values["operator"] + + if "value" in values: + self._value = values["value"] + + if "server" in values: + from bot_graphql.filter.server_filter import ServerFilter + + self._server: ServerFilter = self._services.get_service(ServerFilter) + self._server.from_dict(values["server"]) + + def filter(self, query: List[User]) -> List[User]: + if self._id is not None: + query = query.where(lambda x: x.id == self._id) + + if self._name is not None: + query = query.where(lambda x: x.name == self._name) + + if self._attribute is not None: + query = query.where(lambda x: x.attribute == self._attribute) + + if self._operator is not None: + query = query.where(lambda x: x.operator == self._operator) + + if self._value is not None: + query = query.where(lambda x: x.value == self._value) + + if self._server is not None: + servers = self._server.filter(query.select(lambda x: x.server)).select(lambda x: x.id) + query = query.where(lambda x: x.server.id in servers) + + return query diff --git a/kdb-bot/src/bot_graphql/graphql_module.py b/kdb-bot/src/bot_graphql/graphql_module.py index 5ef7df09..b861aec1 100644 --- a/kdb-bot/src/bot_graphql/graphql_module.py +++ b/kdb-bot/src/bot_graphql/graphql_module.py @@ -8,6 +8,7 @@ from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from bot_data.service.seeder_service import SeederService from bot_graphql.abc.filter_abc import FilterABC from bot_graphql.abc.query_abc import QueryABC +from bot_graphql.filter.achievement_filter import AchievementFilter from bot_graphql.filter.auto_role_filter import AutoRoleFilter from bot_graphql.filter.auto_role_rule_filter import AutoRoleRuleFilter from bot_graphql.filter.client_filter import ClientFilter @@ -19,11 +20,13 @@ from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter from bot_graphql.graphql_service import GraphQLService from bot_graphql.mutation import Mutation +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.user_joined_game_server_mutation import UserJoinedGameServerMutation from bot_graphql.mutations.user_mutation import UserMutation +from bot_graphql.queries.achievement_query import AchievementQuery from bot_graphql.queries.auto_role_history_query import AutoRoleHistoryQuery from bot_graphql.queries.auto_role_query import AutoRoleQuery from bot_graphql.queries.auto_role_rule_history_query import AutoRoleRuleHistoryQuery @@ -76,6 +79,7 @@ class GraphQLModule(ModuleABC): services.add_transient(QueryABC, ServerQuery) services.add_transient(QueryABC, UserHistoryQuery) services.add_transient(QueryABC, UserQuery) + services.add_transient(QueryABC, AchievementQuery) services.add_transient(QueryABC, UserJoinedServerHistoryQuery) services.add_transient(QueryABC, UserJoinedServerQuery) services.add_transient(QueryABC, UserJoinedVoiceChannelHistoryQuery) @@ -90,6 +94,7 @@ class GraphQLModule(ModuleABC): services.add_transient(FilterABC, LevelFilter) services.add_transient(FilterABC, ServerFilter) services.add_transient(FilterABC, UserFilter) + services.add_transient(FilterABC, AchievementFilter) services.add_transient(FilterABC, UserJoinedServerFilter) services.add_transient(FilterABC, UserJoinedVoiceChannelFilter) services.add_transient(FilterABC, UserJoinedGameServerFilter) @@ -99,6 +104,7 @@ class GraphQLModule(ModuleABC): services.add_transient(QueryABC, AutoRoleRuleMutation) services.add_transient(QueryABC, LevelMutation) services.add_transient(QueryABC, UserMutation) + services.add_transient(QueryABC, AchievementMutation) services.add_transient(QueryABC, UserJoinedGameServerMutation) services.add_transient(SeederService) diff --git a/kdb-bot/src/bot_graphql/model/achievement.gql b/kdb-bot/src/bot_graphql/model/achievement.gql new file mode 100644 index 00000000..3a5f1328 --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/achievement.gql @@ -0,0 +1,52 @@ +type Achievement implements TableWithHistoryQuery { + id: ID + name: String + attribute: String + operator: String + value: String + + server: Server + + createdAt: String + modifiedAt: String + + history: [AchievementHistory] +} + +type AchievementHistory implements HistoryTableQuery { + id: ID + name: String + attribute: String + operator: String + value: String + + server: Server + + deleted: Boolean + dateFrom: String + dateTo: String +} + +input AchievementFilter { + id: ID + name: String + attribute: String + operator: String + value: String + server: ServerFilter +} + +type AchievementMutation { + createAchievement(input: AchievementInput!): Achievement + updateAchievement(input: AchievementInput!): Achievement + deleteAchievement(id: ID): Achievement +} + +input AchievementInput { + id: ID + name: String + attribute: String + operator: String + value: String + serverId: ID +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/mutation.gql b/kdb-bot/src/bot_graphql/model/mutation.gql index 9631fd8d..0fb69b50 100644 --- a/kdb-bot/src/bot_graphql/model/mutation.gql +++ b/kdb-bot/src/bot_graphql/model/mutation.gql @@ -4,4 +4,5 @@ type Mutation { level: LevelMutation user: UserMutation userJoinedGameServer: UserJoinedGameServerMutation + achievement: AchievementMutation } \ 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 69b5a74a..17d8634c 100644 --- a/kdb-bot/src/bot_graphql/model/query.gql +++ b/kdb-bot/src/bot_graphql/model/query.gql @@ -29,5 +29,8 @@ type Query { userCount: Int users(filter: UserFilter, page: Page, sort: Sort): [User] + achievementCount: Int + achievements(filter: AchievementFilter, page: Page, sort: Sort): [Achievement] + guilds(filter: GuildFilter): [Guild] } \ 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 56bfa7c5..d8287d96 100644 --- a/kdb-bot/src/bot_graphql/mutation.py +++ b/kdb-bot/src/bot_graphql/mutation.py @@ -1,6 +1,6 @@ from ariadne import MutationType -from bot_data.model.user_joined_game_server import UserJoinedGameServer +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 @@ -15,6 +15,7 @@ class Mutation(MutationType): auto_role_rule_mutation: AutoRoleRuleMutation, level_mutation: LevelMutation, user_mutation: UserMutation, + achievement_mutation: AchievementMutation, user_joined_game_server: UserJoinedGameServerMutation, ): MutationType.__init__(self) @@ -23,4 +24,5 @@ class Mutation(MutationType): self.set_field("autoRoleRule", lambda *_: auto_role_rule_mutation) self.set_field("level", lambda *_: level_mutation) self.set_field("user", lambda *_: user_mutation) + self.set_field("achievement", lambda *_: achievement_mutation) self.set_field("userJoinedGameServer", lambda *_: user_joined_game_server) diff --git a/kdb-bot/src/bot_graphql/mutations/achievement_mutation.py b/kdb-bot/src/bot_graphql/mutations/achievement_mutation.py new file mode 100644 index 00000000..c7daa8c8 --- /dev/null +++ b/kdb-bot/src/bot_graphql/mutations/achievement_mutation.py @@ -0,0 +1,43 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.model.user_role_enum import UserRoleEnum +from bot_graphql.abc.query_abc import QueryABC +from modules.permission.service.permission_service import PermissionService + + +class AchievementMutation(QueryABC): + def __init__( + self, + servers: ServerRepositoryABC, + achievements: AchievementRepositoryABC, + bot: DiscordBotServiceABC, + db: DatabaseContextABC, + permissions: PermissionService, + ): + QueryABC.__init__(self, "AchievementMutation") + + self._servers = servers + self._achievements = achievements + self._bot = bot + self._db = db + self._permissions = permissions + + self.set_field("updateAchievement", self.resolve_update_achievement) + + def resolve_update_achievement(self, *_, input: dict): + achievement = self._achievements.get_achievement_by_id(input["id"]) + self._can_user_mutate_data(achievement.server, UserRoleEnum.moderator) + + achievement.name = input["name"] if "name" in input else achievement.name + achievement.attribute = input["attribute"] if "attribute" in input else achievement.attribute + achievement.operator = input["operator"] if "operator" in input else achievement.operator + achievement.value = input["value"] if "value" in input else achievement.value + + self._achievements.update_achievement(achievement) + self._db.save_changes() + + achievement = self._achievements.get_achievement_by_id(input["id"]) + return achievement diff --git a/kdb-bot/src/bot_graphql/queries/achievement_query.py b/kdb-bot/src/bot_graphql/queries/achievement_query.py new file mode 100644 index 00000000..c9782973 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/achievement_query.py @@ -0,0 +1,19 @@ +from cpl_core.database.context import DatabaseContextABC + +from bot_data.model.user_history import UserHistory +from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC + + +class AchievementQuery(DataQueryWithHistoryABC): + def __init__( + self, + db: DatabaseContextABC, + ): + DataQueryWithHistoryABC.__init__(self, "Achievement", "AchievementsHistory", UserHistory, db) + + self.set_field("id", lambda x: x.id) + self.set_field("name", lambda x: x.name) + self.set_field("attribute", lambda x: x.attribute) + self.set_field("operator", lambda x: x.operator) + self.set_field("value", lambda x: x.value) + self.set_field("server", lambda x: x.server) diff --git a/kdb-bot/src/bot_graphql/query.py b/kdb-bot/src/bot_graphql/query.py index 8133e4dc..976b1950 100644 --- a/kdb-bot/src/bot_graphql/query.py +++ b/kdb-bot/src/bot_graphql/query.py @@ -1,5 +1,6 @@ from cpl_discord.service import DiscordBotServiceABC +from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC from bot_data.abc.client_repository_abc import ClientRepositoryABC from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC @@ -10,6 +11,7 @@ from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepos from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_graphql.abc.query_abc import QueryABC +from bot_graphql.filter.achievement_filter import AchievementFilter from bot_graphql.filter.auto_role_filter import AutoRoleFilter from bot_graphql.filter.auto_role_rule_filter import AutoRoleRuleFilter from bot_graphql.filter.client_filter import ClientFilter @@ -34,6 +36,7 @@ class Query(QueryABC): user_joined_voice_channels: UserJoinedVoiceChannelRepositoryABC, user_joined_game_server: UserJoinedGameServerRepositoryABC, users: UserRepositoryABC, + achievements: AchievementRepositoryABC, ): QueryABC.__init__(self, "Query") @@ -59,6 +62,7 @@ class Query(QueryABC): UserJoinedGameServerFilter, ) self.add_collection("user", lambda *_: users.get_users(), UserFilter) + self.add_collection("achievement", lambda *_: achievements.get_achievements(), AchievementFilter) self.set_field("guilds", self._resolve_guilds) diff --git a/kdb-web/package.json b/kdb-web/package.json index 8e415632..e77d9ec0 100644 --- a/kdb-web/package.json +++ b/kdb-web/package.json @@ -51,4 +51,4 @@ "tslib": "^2.4.1", "typescript": "~4.9.5" } -} +} \ No newline at end of file diff --git a/kdb-web/src/assets/config.json b/kdb-web/src/assets/config.json index f9117e39..57eaafa7 100644 --- a/kdb-web/src/assets/config.json +++ b/kdb-web/src/assets/config.json @@ -25,4 +25,4 @@ "Name": "sh-edraft-dark-theme" } ] -} +} \ No newline at end of file -- 2.45.2 From bfb816dd17e03934d005de1902338709e753b3fe Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 12 Jul 2023 11:23:14 +0200 Subject: [PATCH 017/127] Fixed achievement query #268_achievements --- .../migration/achievements_migration.py | 2 +- kdb-bot/src/bot_data/model/achievement.py | 8 ++++ .../achievements_repository_service.py | 6 +-- .../mutations/achievement_mutation.py | 37 +++++++++++++++++++ .../bot_graphql/mutations/level_mutation.py | 1 + .../bot_graphql/queries/achievement_query.py | 12 +++--- 6 files changed, 56 insertions(+), 10 deletions(-) diff --git a/kdb-bot/src/bot_data/migration/achievements_migration.py b/kdb-bot/src/bot_data/migration/achievements_migration.py index 160d379c..294d1b8b 100644 --- a/kdb-bot/src/bot_data/migration/achievements_migration.py +++ b/kdb-bot/src/bot_data/migration/achievements_migration.py @@ -20,11 +20,11 @@ class AchievementsMigration(MigrationABC): f""" CREATE TABLE IF NOT EXISTS `Achievements` ( `Id` BIGINT NOT NULL AUTO_INCREMENT, - `ServerId` BIGINT, `Name` VARCHAR(255) NOT NULL, `Attribute` VARCHAR(255) NOT NULL, `Operator` VARCHAR(2) NOT NULL, `Value` VARCHAR(255) NOT NULL, + `ServerId` BIGINT, `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6), `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), PRIMARY KEY(`Id`), diff --git a/kdb-bot/src/bot_data/model/achievement.py b/kdb-bot/src/bot_data/model/achievement.py index b9a44089..a4c8b831 100644 --- a/kdb-bot/src/bot_data/model/achievement.py +++ b/kdb-bot/src/bot_data/model/achievement.py @@ -41,6 +41,14 @@ class Achievement(TableABC): def name(self, value: str): self._name = value + @property + def attribute(self) -> str: + return self._attribute + + @attribute.setter + def attribute(self, value: str): + self._attribute = value + @property def operator(self) -> str: return self._operator diff --git a/kdb-bot/src/bot_data/service/achievements_repository_service.py b/kdb-bot/src/bot_data/service/achievements_repository_service.py index d910a6c2..d9c157e2 100644 --- a/kdb-bot/src/bot_data/service/achievements_repository_service.py +++ b/kdb-bot/src/bot_data/service/achievements_repository_service.py @@ -23,11 +23,11 @@ class AchievementRepositoryService(AchievementRepositoryABC): def _from_result(self, result: tuple): return Achievement( + result[1], + result[2], result[3], result[4], - result[5], - result[6], - self._servers.get_server_by_id(result[2]), + self._servers.get_server_by_id(result[5]), result[6], result[7], id=result[0], diff --git a/kdb-bot/src/bot_graphql/mutations/achievement_mutation.py b/kdb-bot/src/bot_graphql/mutations/achievement_mutation.py index c7daa8c8..99459515 100644 --- a/kdb-bot/src/bot_graphql/mutations/achievement_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/achievement_mutation.py @@ -3,6 +3,7 @@ from cpl_discord.service import DiscordBotServiceABC from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.model.achievement import Achievement from bot_data.model.user_role_enum import UserRoleEnum from bot_graphql.abc.query_abc import QueryABC from modules.permission.service.permission_service import PermissionService @@ -25,7 +26,34 @@ class AchievementMutation(QueryABC): self._db = db self._permissions = permissions + self.set_field("createAchievement", self.resolve_create_achievement) self.set_field("updateAchievement", self.resolve_update_achievement) + self.set_field("deleteAchievement", self.resolve_delete_achievement) + + def resolve_create_achievement(self, *_, input: dict): + server = self._servers.get_server_by_id(input["serverId"]) + self._can_user_mutate_data(server, UserRoleEnum.admin) + + achievement = Achievement( + input["name"], + input["attribute"], + input["operator"], + input["value"], + server, + ) + self._achievements.add_achievement(achievement) + self._db.save_changes() + + def get_new_achievement(a: Achievement): + return ( + a.name == achievement.name + and a.attribute == achievement.attribute + and a.operator == achievement.operator + and a.value == achievement.value + and a.server.id == server.id + ) + + return self._achievements.get_achievements_by_server_id(achievement.server.id).where(get_new_achievement).last() def resolve_update_achievement(self, *_, input: dict): achievement = self._achievements.get_achievement_by_id(input["id"]) @@ -41,3 +69,12 @@ class AchievementMutation(QueryABC): achievement = self._achievements.get_achievement_by_id(input["id"]) return achievement + + def resolve_delete_achievement(self, *_, id: int): + achievement = self._achievements.get_achievement_by_id(id) + self._can_user_mutate_data(achievement.server, UserRoleEnum.admin) + + self._achievements.delete_achievement(achievement) + self._db.save_changes() + + return achievement diff --git a/kdb-bot/src/bot_graphql/mutations/level_mutation.py b/kdb-bot/src/bot_graphql/mutations/level_mutation.py index 47f61e7c..215538b7 100644 --- a/kdb-bot/src/bot_graphql/mutations/level_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/level_mutation.py @@ -50,6 +50,7 @@ class LevelMutation(QueryABC): and l.color == level.color and l.min_xp == level.min_xp and l.permissions == level.permissions + and l.server.id == server.id ) self._bot.loop.create_task(self._level_seeder.seed()) diff --git a/kdb-bot/src/bot_graphql/queries/achievement_query.py b/kdb-bot/src/bot_graphql/queries/achievement_query.py index c9782973..46ee137d 100644 --- a/kdb-bot/src/bot_graphql/queries/achievement_query.py +++ b/kdb-bot/src/bot_graphql/queries/achievement_query.py @@ -11,9 +11,9 @@ class AchievementQuery(DataQueryWithHistoryABC): ): DataQueryWithHistoryABC.__init__(self, "Achievement", "AchievementsHistory", UserHistory, db) - self.set_field("id", lambda x: x.id) - self.set_field("name", lambda x: x.name) - self.set_field("attribute", lambda x: x.attribute) - self.set_field("operator", lambda x: x.operator) - self.set_field("value", lambda x: x.value) - self.set_field("server", lambda x: x.server) + self.set_field("id", lambda x, *_: x.id) + self.set_field("name", lambda x, *_: x.name) + self.set_field("attribute", lambda x, *_: x.attribute) + self.set_field("operator", lambda x, *_: x.operator) + self.set_field("value", lambda x, *_: x.value) + self.set_field("server", lambda x, *_: x.server) -- 2.45.2 From f312a2d776eb163a2361eeac354cf3e3f7c93b01 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 12 Jul 2023 11:26:21 +0200 Subject: [PATCH 018/127] Fixed achievement query #268_achievements --- kdb-bot/src/bot_data/model/achievement.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kdb-bot/src/bot_data/model/achievement.py b/kdb-bot/src/bot_data/model/achievement.py index a4c8b831..e01bafad 100644 --- a/kdb-bot/src/bot_data/model/achievement.py +++ b/kdb-bot/src/bot_data/model/achievement.py @@ -106,7 +106,7 @@ class Achievement(TableABC): def udpate_string(self) -> str: return str( f""" - UPDATE `Levels` + UPDATE `Achievements` SET `Name` = '{self._name}', `Attribute` = '{self._attribute}', `Operator` = '{self._operator}', -- 2.45.2 From a0d38bec49131a14451e66e8850ef77ae8e526e3 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 12 Jul 2023 11:56:52 +0200 Subject: [PATCH 019/127] First step to add achievements to frontend #268_achievements --- kdb-bot/src/bot_graphql/model/server.gql | 3 + .../src/bot_graphql/queries/server_query.py | 7 +- .../src/app/models/data/achievement.model.ts | 20 ++ .../src/app/models/graphql/mutations.model.ts | 42 +++ .../src/app/models/graphql/queries.model.ts | 44 +++ kdb-web/src/app/models/graphql/query.model.ts | 6 + .../src/app/models/graphql/result.model.ts | 9 + .../achievements-routing.module.ts | 16 ++ .../achievements/achievements.module.ts | 18 ++ .../achievement/achievement.component.html | 215 ++++++++++++++ .../achievement/achievement.component.scss | 0 .../achievement/achievement.component.spec.ts | 23 ++ .../achievement/achievement.component.ts | 268 ++++++++++++++++++ .../view/server/server-routing.module.ts | 3 +- .../app/services/sidebar/sidebar.service.ts | 11 +- kdb-web/src/assets/i18n/de.json | 26 ++ 16 files changed, 708 insertions(+), 3 deletions(-) create mode 100644 kdb-web/src/app/models/data/achievement.model.ts create mode 100644 kdb-web/src/app/modules/view/server/achievements/achievements-routing.module.ts create mode 100644 kdb-web/src/app/modules/view/server/achievements/achievements.module.ts create mode 100644 kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html create mode 100644 kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.scss create mode 100644 kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.spec.ts create mode 100644 kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.ts diff --git a/kdb-bot/src/bot_graphql/model/server.gql b/kdb-bot/src/bot_graphql/model/server.gql index db94dc89..90f07f95 100644 --- a/kdb-bot/src/bot_graphql/model/server.gql +++ b/kdb-bot/src/bot_graphql/model/server.gql @@ -16,6 +16,9 @@ type Server implements TableWithHistoryQuery { userCount: Int users(filter: UserFilter, page: Page, sort: Sort): [User] + achievementCount: Int + achievements(filter: AchievementFilter, page: Page, sort: Sort): [Achievement] + createdAt: String modifiedAt: String diff --git a/kdb-bot/src/bot_graphql/queries/server_query.py b/kdb-bot/src/bot_graphql/queries/server_query.py index 39012d49..52d53d23 100644 --- a/kdb-bot/src/bot_graphql/queries/server_query.py +++ b/kdb-bot/src/bot_graphql/queries/server_query.py @@ -1,6 +1,7 @@ from cpl_core.database.context import DatabaseContextABC from cpl_discord.service import DiscordBotServiceABC +from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC from bot_data.abc.client_repository_abc import ClientRepositoryABC from bot_data.abc.level_repository_abc import LevelRepositoryABC @@ -9,8 +10,8 @@ from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoic from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.model.server import Server from bot_data.model.server_history import ServerHistory -from bot_graphql.abc.data_query_abc import DataQueryABC from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC +from bot_graphql.filter.achievement_filter import AchievementFilter from bot_graphql.filter.auto_role_filter import AutoRoleFilter from bot_graphql.filter.client_filter import ClientFilter from bot_graphql.filter.level_filter import LevelFilter @@ -28,6 +29,7 @@ class ServerQuery(DataQueryWithHistoryABC): users: UserRepositoryABC, ujs: UserJoinedServerRepositoryABC, ujvs: UserJoinedVoiceChannelRepositoryABC, + achievements: AchievementRepositoryABC, ): DataQueryWithHistoryABC.__init__(self, "Server", "ServersHistory", ServerHistory, db) @@ -54,6 +56,9 @@ class ServerQuery(DataQueryWithHistoryABC): ) self.add_collection("level", lambda server, *_: self._levels.get_levels_by_server_id(server.id), LevelFilter) self.add_collection("user", lambda server, *_: self._users.get_users_by_server_id(server.id), UserFilter) + self.add_collection( + "achievement", lambda server, *_: achievements.get_achievements_by_server_id(server.id), AchievementFilter + ) @staticmethod def resolve_id(server: Server, *_): diff --git a/kdb-web/src/app/models/data/achievement.model.ts b/kdb-web/src/app/models/data/achievement.model.ts new file mode 100644 index 00000000..0b1af096 --- /dev/null +++ b/kdb-web/src/app/models/data/achievement.model.ts @@ -0,0 +1,20 @@ +import { DataWithHistory } from "./data.model"; +import { Server, ServerFilter } from "./server.model"; + +export interface Achievement extends DataWithHistory { + id?: number; + name?: string; + attribute?: string; + operator?: string; + value?: string; + server?: Server; +} + +export interface AchievementFilter { + id?: number; + name?: string; + attribute?: string; + operator?: string; + value?: string; + server?: ServerFilter; +} diff --git a/kdb-web/src/app/models/graphql/mutations.model.ts b/kdb-web/src/app/models/graphql/mutations.model.ts index 0cba6ef3..db95bd86 100644 --- a/kdb-web/src/app/models/graphql/mutations.model.ts +++ b/kdb-web/src/app/models/graphql/mutations.model.ts @@ -121,4 +121,46 @@ export class Mutations { } } `; + + static createAchievement = ` + mutation createAchievement($name: String, $attribute: String, $operator: String, $value: String, $serverId: ID) { + level { + createAchievement(input: { name: $name, attribute: $attribute, operator: $operator, value: $value, serverId: $serverId}) { + id + name + attribute + operator + value + server { + id + } + } + } + } + `; + + static updateAchievement = ` + mutation updateAchievement($name: String, $attribute: String, $operator: String, $value: String, $serverId: ID) { + level { + updateAchievement(input: { name: $name, attribute: $attribute, operator: $operator, value: $value}) { + id + name + attribute + operator + value + } + } + } + `; + + static deleteAchievement = ` + mutation deleteAchievement($id: ID) { + level { + deleteLevel(id: $id) { + id + name + } + } + } + `; } diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts index f3d68257..df3cf125 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -90,6 +90,50 @@ export class Queries { } `; + static achievementQuery = ` + query AchievementList($serverId: ID, $filter: AchievementFilter, $page: Page, $sort: Sort) { + servers(filter: {id: $serverId}) { + achievementCount + achievements(filter: $filter, page: $page, sort: $sort) { + id + name + attribute + operator + value + server { + id + name + } + createdAt + modifiedAt + } + } + } + `; + + static achievementWithHistoryQuery = ` + query AchievementHistory($serverId: ID, $id: ID) { + servers(filter: {id: $serverId}) { + achievementCount + achievements(filter: {id: $id}) { + id + + history { + id + name + attribute + operator + value + server + deleted + dateFrom + dateTo + } + } + } + } + `; + static usersQuery = ` query UsersList($serverId: ID, $filter: UserFilter, $page: Page, $sort: Sort) { servers(filter: {id: $serverId}) { diff --git a/kdb-web/src/app/models/graphql/query.model.ts b/kdb-web/src/app/models/graphql/query.model.ts index 3f7e85a1..60e1964d 100644 --- a/kdb-web/src/app/models/graphql/query.model.ts +++ b/kdb-web/src/app/models/graphql/query.model.ts @@ -3,6 +3,7 @@ import { User } from "../data/user.model"; import { AutoRole, AutoRoleRule } from "../data/auto_role.model"; import { Guild } from "../data/discord.model"; import { Level } from "../data/level.model"; +import { Achievement } from "../data/achievement.model"; export interface Query { serverCount: number; @@ -23,6 +24,11 @@ export interface LevelListQuery { levels: Level[]; } +export interface AchievementListQuery { + achievementCount: number; + achievements: Achievement[]; +} + export interface AutoRoleQuery { autoRoleCount: number; autoRoles: AutoRole[]; diff --git a/kdb-web/src/app/models/graphql/result.model.ts b/kdb-web/src/app/models/graphql/result.model.ts index d3d6e4a4..d77c2cdc 100644 --- a/kdb-web/src/app/models/graphql/result.model.ts +++ b/kdb-web/src/app/models/graphql/result.model.ts @@ -2,6 +2,7 @@ import { User } from "../data/user.model"; 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"; export interface GraphQLResult { data: { @@ -45,3 +46,11 @@ export interface LevelMutationResult { deleteLevel?: Level }; } + +export interface AchievementMutationResult { + achievement: { + createAchievement?: Achievement + updateAchievement?: Achievement + deleteAchievement?: Achievement + }; +} diff --git a/kdb-web/src/app/modules/view/server/achievements/achievements-routing.module.ts b/kdb-web/src/app/modules/view/server/achievements/achievements-routing.module.ts new file mode 100644 index 00000000..ae847fb9 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/achievements/achievements-routing.module.ts @@ -0,0 +1,16 @@ +import {NgModule} from "@angular/core"; +import {RouterModule, Routes} from "@angular/router"; +import { AchievementComponent } from "./components/achievement/achievement.component"; + +const routes: Routes = [ + + {path: '', component: AchievementComponent}, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class AchievementsRoutingModule { + +} diff --git a/kdb-web/src/app/modules/view/server/achievements/achievements.module.ts b/kdb-web/src/app/modules/view/server/achievements/achievements.module.ts new file mode 100644 index 00000000..ccf7e426 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/achievements/achievements.module.ts @@ -0,0 +1,18 @@ +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; +import { AchievementComponent } from "./components/achievement/achievement.component"; +import { AchievementsRoutingModule } from "./achievements-routing.module"; +import { SharedModule } from "../../../shared/shared.module"; + + +@NgModule({ + declarations: [ + AchievementComponent + ], + imports: [ + CommonModule, + AchievementsRoutingModule, + SharedModule + ] +}) +export class AchievementsModule { } diff --git a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html new file mode 100644 index 00000000..83879d48 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html @@ -0,0 +1,215 @@ +

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

+
+
+ + + +
+
+ {{achievements.length}} {{'common.of' | translate}} + {{dt.totalRecords}} + + {{'view.server.achievements.achievements' | translate}} +
+ +
+ + +
+
+
+ + + + +
+
{{'common.id' | translate}}
+ +
+ + + +
+
{{'view.server.achievements.headers.name' | translate}}
+ +
+ + + +
+
{{'view.server.achievements.headers.attribute' | translate}}
+ +
+ + + +
+
{{'view.server.achievements.headers.operator' | translate}}
+ +
+ + + +
+
{{'view.server.achievements.headers.value' | translate}}
+ +
+ + + +
+
{{'common.created_at' | translate}}
+
+ + + +
+
{{'common.modified_at' | translate}}
+
+ + + +
+
{{'common.actions' | translate}}
+
+ + + + + +
+ +
+ + +
+ +
+ + + + + + + + +
+ + + + + + + {{achievement.id}} + + + {{achievement.id}} + + + + + + + + + + + {{achievement.name}} + + + + + + + + + + + {{achievement.attribute}} + + + + + + + + + + + {{achievement.operator}} + + + + + + + + + + + {{achievement.value}} + + + + + + + + {{achievement.createdAt | date:'dd.MM.yy HH:mm'}} + + + {{achievement.createdAt | date:'dd.MM.yy HH:mm'}} + + + + + + + {{achievement.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + {{achievement.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + + +
+ + + + + + +
+ + +
+ + + + + {{'common.no_entries_found' | translate}} + + + + + + +
+
+
+ diff --git a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.scss b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.spec.ts b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.spec.ts new file mode 100644 index 00000000..771e808b --- /dev/null +++ b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AchievementComponent } from './achievement.component'; + +describe('AchievementComponent', () => { + let component: AchievementComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AchievementComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(AchievementComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); 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 new file mode 100644 index 00000000..5eb90432 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.ts @@ -0,0 +1,268 @@ +import { Component, OnDestroy, OnInit } from "@angular/core"; +import { Achievement, AchievementFilter } from "../../../../../../models/data/achievement.model"; +import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; +import { Page } from "../../../../../../models/graphql/filter/page.model"; +import { Sort, SortDirection } from "../../../../../../models/graphql/filter/sort.model"; +import { Subject, throwError } from "rxjs"; +import { Server } from "../../../../../../models/data/server.model"; +import { UserDTO } from "../../../../../../models/auth/auth-user.dto"; +import { Queries } from "../../../../../../models/graphql/queries.model"; +import { AuthService } from "../../../../../../services/auth/auth.service"; +import { SpinnerService } from "../../../../../../services/spinner/spinner.service"; +import { ToastService } from "../../../../../../services/toast/toast.service"; +import { ConfirmationDialogService } from "../../../../../../services/confirmation-dialog/confirmation-dialog.service"; +import { TranslateService } from "@ngx-translate/core"; +import { DataService } from "../../../../../../services/data/data.service"; +import { SidebarService } from "../../../../../../services/sidebar/sidebar.service"; +import { ActivatedRoute } from "@angular/router"; +import { AchievementListQuery, Query } from "../../../../../../models/graphql/query.model"; +import { catchError, debounceTime, takeUntil } from "rxjs/operators"; +import { LazyLoadEvent } from "primeng/api"; +import { Table } from "primeng/table"; +import { User } from "../../../../../../models/data/user.model"; +import { AchievementMutationResult, UpdateUserMutationResult } from "../../../../../../models/graphql/result.model"; +import { Mutations } from "../../../../../../models/graphql/mutations.model"; + +@Component({ + selector: "app-achievement", + templateUrl: "./achievement.component.html", + styleUrls: ["./achievement.component.scss"] +}) +export class AchievementComponent implements OnInit, OnDestroy { + public achievements: Achievement[] = []; + public loading = true; + + public isEditingNew: boolean = false; + + public filterForm!: FormGroup<{ + id: FormControl, + name: FormControl, + color: FormControl, + min_xp: FormControl, + permissions: FormControl, + }>; + + public filter: AchievementFilter = {}; + public page: Page = { + pageSize: undefined, + pageIndex: undefined + }; + public sort: Sort = { + sortColumn: undefined, + sortDirection: undefined + }; + + public totalRecords: number = 0; + + public clonedAchievements: { [s: string]: Achievement; } = {}; + + private unsubscriber = new Subject(); + private server: Server = {}; + public user: UserDTO | null = null; + + query: string = Queries.achievementWithHistoryQuery; + + public constructor( + private authService: AuthService, + private spinner: SpinnerService, + private toastService: ToastService, + private confirmDialog: ConfirmationDialogService, + private fb: FormBuilder, + private translate: TranslateService, + private data: DataService, + private sidebar: SidebarService, + private route: ActivatedRoute) { + } + + public ngOnInit(): void { + this.setFilterForm(); + this.data.getServerFromRoute(this.route).then(async server => { + this.server = server; + this.loadNextPage(); + let authUser = await this.authService.getLoggedInUser(); + this.user = authUser?.users?.find(u => u.server == this.server.id) ?? null; + }); + } + + public ngOnDestroy(): void { + this.unsubscriber.next(); + this.unsubscriber.complete(); + } + + public loadNextPage(): void { + this.loading = true; + this.data.query(Queries.achievementQuery, { + serverId: this.server.id, filter: this.filter, page: this.page, sort: this.sort + }, + (data: Query) => { + return data.servers[0]; + } + ).subscribe(data => { + this.totalRecords = data.achievementCount; + this.achievements = data.achievements; + this.spinner.hideSpinner(); + this.loading = false; + }); + } + + public setFilterForm(): void { + this.filterForm = this.fb.group({ + id: new FormControl(null), + name: new FormControl(null), + color: new FormControl(null), + min_xp: new FormControl(null), + permissions: new FormControl(null) + }); + + this.filterForm.valueChanges.pipe( + takeUntil(this.unsubscriber), + debounceTime(600) + ).subscribe(changes => { + if (changes.id) { + this.filter.id = changes.id; + } else { + this.filter.id = undefined; + } + + if (changes.name) { + this.filter.name = changes.name; + } else { + this.filter.name = undefined; + } + + if (this.page.pageSize) + this.page.pageSize = 10; + + if (this.page.pageIndex) + this.page.pageIndex = 0; + + this.loadNextPage(); + }); + } + + public newAchievementTemplate: Achievement = { + id: 0, + createdAt: "", + modifiedAt: "" + }; + + public nextPage(event: LazyLoadEvent): void { + this.page.pageSize = event.rows ?? 0; + if (event.first != null && event.rows != null) + this.page.pageIndex = event.first / event.rows; + this.sort.sortColumn = event.sortField ?? undefined; + this.sort.sortDirection = event.sortOrder === 1 ? SortDirection.ASC : event.sortOrder === -1 ? SortDirection.DESC : SortDirection.ASC; + + this.loadNextPage(); + } + + public resetFilters(): void { + this.filterForm.reset(); + } + + public onRowEditInit(table: Table, user: User, index: number): void { + this.clonedAchievements[index] = { ...user }; + } + + public onRowEditSave(table: Table, newAchievement: Achievement, index: number): void { + if (this.isEditingNew && JSON.stringify(newAchievement) === JSON.stringify(this.newAchievementTemplate)) { + this.isEditingNew = false; + this.achievements.splice(index, 1); + return; + } + + if (!newAchievement.id && !this.isEditingNew || !newAchievement.name && !newAchievement.attribute && !newAchievement?.operator && !newAchievement?.value) { + return; + } + + if (this.isEditingNew) { + this.spinner.showSpinner(); + this.data.mutation(Mutations.createAchievement, { + name: newAchievement.name, + attribute: newAchievement.attribute, + operator: newAchievement.operator, + value: newAchievement.value, + serverId: this.server.id + } + ).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; + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.achievements.message.achievement_create"), this.translate.instant("view.server.achievements.message.achievement_create_d", { name: result.achievement.createAchievement?.name })); + this.loadNextPage(); + }); + return; + } + + this.spinner.showSpinner(); + this.data.mutation(Mutations.updateAchievement, { + id: newAchievement.id, + name: newAchievement.name, + attribute: newAchievement.attribute, + operator: newAchievement.operator, + value: newAchievement.value + } + ).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(); + this.toastService.success(this.translate.instant("view.server.achievements.message.achievement_update"), this.translate.instant("view.server.achievements.message.achievement_update_d", { name: newAchievement.name })); + this.loadNextPage(); + }); + + } + + public onRowEditCancel(index: number): void { + if (this.isEditingNew) { + this.achievements.splice(index, 1); + delete this.clonedAchievements[index]; + this.isEditingNew = false; + return; + } + + this.achievements[index] = this.clonedAchievements[index]; + delete this.clonedAchievements[index]; + } + + public deleteAchievement(achievement: Achievement): void { + this.confirmDialog.confirmDialog( + this.translate.instant("view.server.achievements.message.achievement_delete"), this.translate.instant("view.server.achievements.message.achievement_delete_q", { name: achievement.name }), + () => { + this.spinner.showSpinner(); + this.data.mutation(Mutations.deleteAchievement, { + id: achievement.id + } + ).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(); + this.toastService.success(this.translate.instant("view.server.achievements.message.achievement_deleted"), this.translate.instant("view.server.achievements.message.achievement_deleted_d", { name: achievement.name })); + this.loadNextPage(); + }); + }); + } + + public addAchievement(table: Table): void { + const newAchievement = JSON.parse(JSON.stringify(this.newAchievementTemplate)); + newAchievement.id = Math.max.apply(Math, this.achievements.map(l => { + return l.id ?? 0; + })) + 1; + + this.achievements.push(newAchievement); + + table.initRowEdit(newAchievement); + + const index = this.achievements.findIndex(l => l.id == newAchievement.id); + this.onRowEditInit(table, newAchievement, index); + + this.isEditingNew = true; + } +} 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 147c40ea..a83dab96 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 @@ -9,7 +9,8 @@ const routes: Routes = [ { path: "members", component: MembersComponent }, { 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: "levels", loadChildren: () => import("./levels/levels.module").then(m => m.LevelsModule) }, + { path: "achievements", loadChildren: () => import("./achievements/achievements.module").then(m => m.AchievementsModule) } ]; @NgModule({ diff --git a/kdb-web/src/app/services/sidebar/sidebar.service.ts b/kdb-web/src/app/services/sidebar/sidebar.service.ts index 1bd9476a..81ab4548 100644 --- a/kdb-web/src/app/services/sidebar/sidebar.service.ts +++ b/kdb-web/src/app/services/sidebar/sidebar.service.ts @@ -24,6 +24,7 @@ export class SidebarService { serverMembers: MenuItem = {}; serverAutoRoles: MenuItem = {}; serverLevels: MenuItem = {}; + serverAchievements: MenuItem = {}; serverMenu: MenuItem = {}; adminConfig: MenuItem = {}; adminUsers: MenuItem = {}; @@ -102,12 +103,19 @@ export class SidebarService { routerLink: `server/${this.server$.value?.id}/levels` }; + this.serverAchievements = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.achievements") : "", + icon: "pi pi-angle-double-up", + visible: true, + routerLink: `server/${this.server$.value?.id}/achievements` + }; + 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] + items: [this.serverDashboard, this.serverProfile, this.serverMembers, this.serverAutoRoles, this.serverLevels, this.serverAchievements] }; this.adminConfig = { label: this.isSidebarOpen ? this.translateService.instant("sidebar.config") : "", @@ -142,6 +150,7 @@ export class SidebarService { this.serverMembers.visible = !!user?.isModerator; this.serverAutoRoles.visible = !!user?.isModerator; this.serverLevels.visible = !!user?.isModerator; + this.serverAchievements.visible = !!user?.isModerator; } else { this.serverMenu.visible = false; } diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index 7a1cdf40..4078a0be 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -397,6 +397,32 @@ "level_update_failed_d": "Die Bearbeitung des Levels ist fehlgeschlagen!" } }, + "achievements": { + "header": "Errungenschaften", + "headers": { + "name": "Name", + "attribute": "Attribut", + "operator": "Operator", + "value": "Wert" + }, + "achievements": "Errungenschaften", + "message": { + "achievement_create": "Errungenschaft erstellt", + "achievement_create_d": "Errungenschaft {{name}} erfolgreich erstellt", + "achievement_create_failed": "Errungenschaft Erstellung fehlgeschlagen", + "achievement_create_failed_d": "Die Erstellung der Errungenschaft ist fehlgeschlagen!", + "achievement_delete": "Errungenschaft löschen", + "achievement_delete_failed": "Errungenschaft Löschung fehlgeschlagen", + "achievement_delete_failed_d": "Die Löschung der Errungenschaft {{name}} ist fehlgeschlagen!", + "achievement_delete_q": "Sind Sie sich sicher, dass Sie das Errungenschaft {{name}} löschen möchten?", + "achievement_deleted": "Errungenschaft gelöscht", + "achievement_deleted_d": "Errungenschaft {{name}} erfolgreich gelöscht", + "achievement_update": "Errungenschaft bearbeitet", + "achievement_update_d": "Errungenschaft {{name}} erfolgreich bearbeitet", + "achievement_update_failed": "Errungenschaft Bearbeitung fehlgeschlagen", + "achievement_update_failed_d": "Die Bearbeitung der Errungenschaft ist fehlgeschlagen!" + } + }, "members": { "header": "Mitglieder", "headers": { -- 2.45.2 From b99dd1bded66dcddef8849feb1000919e91fb2a8 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 12 Jul 2023 13:11:26 +0200 Subject: [PATCH 020/127] Fixed server cache & improved frontend implementation #268_achievements --- kdb-bot/src/bot_data/service/cache_service.py | 19 ++++++++++++++----- .../service/server_repository_service.py | 5 +++-- .../src/app/models/graphql/mutations.model.ts | 12 ++++++------ .../achievement/achievement.component.html | 12 ++++++------ kdb-web/src/assets/i18n/de.json | 3 ++- 5 files changed, 31 insertions(+), 20 deletions(-) diff --git a/kdb-bot/src/bot_data/service/cache_service.py b/kdb-bot/src/bot_data/service/cache_service.py index 31dcd73a..50d05e7e 100644 --- a/kdb-bot/src/bot_data/service/cache_service.py +++ b/kdb-bot/src/bot_data/service/cache_service.py @@ -5,12 +5,21 @@ from bot_data.model.server import Server class CacheService: def __init__(self): - self._cached_server = List(Server) + self._cached_servers = List(Server) @property def cached_server(self) -> List[Server]: - return self._cached_server + return self._cached_servers - @cached_server.setter - def cached_server(self, value: List[Server]): - self._cached_server = value + def add_server(self, server: Server): + if self._cached_servers.where(lambda x: x.id == server.id).count() > 0: + return + self._cached_servers.add(server) + + def add_servers(self, servers: List[Server]): + new_ids = servers.select(lambda x: x.id) + for s in self._cached_servers: + if s.id in new_ids: + return + + self._cached_servers.extend(servers) diff --git a/kdb-bot/src/bot_data/service/server_repository_service.py b/kdb-bot/src/bot_data/service/server_repository_service.py index 2d158fad..924cc036 100644 --- a/kdb-bot/src/bot_data/service/server_repository_service.py +++ b/kdb-bot/src/bot_data/service/server_repository_service.py @@ -26,7 +26,7 @@ class ServerRepositoryService(ServerRepositoryABC): for result in results: servers.append(Server(result[1], result[2], result[3], id=result[0])) - self._cache.cached_server = List(Server, servers) + self._cache.add_servers(servers) return servers def get_filtered_servers(self, criteria: ServerSelectCriteria) -> FilteredResult: @@ -56,13 +56,14 @@ class ServerRepositoryService(ServerRepositoryABC): def get_server_by_id(self, server_id: int) -> Server: cs = self._cache.cached_server.where(lambda x: x.id == server_id).single_or_default() + if cs is not None: return cs self._logger.trace(__name__, f"Send SQL command: {Server.get_select_by_id_string(server_id)}") result = self._context.select(Server.get_select_by_id_string(server_id))[0] server = Server(result[1], result[2], result[3], id=result[0]) - self._cache.cached_server.add(server) + self._cache.add_server(server) return server def get_server_by_discord_id(self, discord_id: int) -> Server: diff --git a/kdb-web/src/app/models/graphql/mutations.model.ts b/kdb-web/src/app/models/graphql/mutations.model.ts index db95bd86..df3b539d 100644 --- a/kdb-web/src/app/models/graphql/mutations.model.ts +++ b/kdb-web/src/app/models/graphql/mutations.model.ts @@ -124,7 +124,7 @@ export class Mutations { static createAchievement = ` mutation createAchievement($name: String, $attribute: String, $operator: String, $value: String, $serverId: ID) { - level { + achievement { createAchievement(input: { name: $name, attribute: $attribute, operator: $operator, value: $value, serverId: $serverId}) { id name @@ -140,9 +140,9 @@ export class Mutations { `; static updateAchievement = ` - mutation updateAchievement($name: String, $attribute: String, $operator: String, $value: String, $serverId: ID) { - level { - updateAchievement(input: { name: $name, attribute: $attribute, operator: $operator, value: $value}) { + mutation updateAchievement($id: ID, $name: String, $attribute: String, $operator: String, $value: String) { + achievement { + updateAchievement(input: { id: $id, name: $name, attribute: $attribute, operator: $operator, value: $value}) { id name attribute @@ -155,8 +155,8 @@ export class Mutations { static deleteAchievement = ` mutation deleteAchievement($id: ID) { - level { - deleteLevel(id: $id) { + achievement { + deleteAchievement(id: $id) { id name } diff --git a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html index 83879d48..7bdfc233 100644 --- a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html +++ b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html @@ -18,7 +18,7 @@
+ (click)="onRowEditInit(dt, achievement, ri)" [disabled]="!user || !user.isModerator && !user.isAdmin"> + (click)="deleteAchievement(achievement)" [disabled]="!user || !user.isModerator && !user.isAdmin"> + icon="pi pi-check-circle" (click)="onRowEditSave(dt, achievement, ri)" [disabled]="!user || !user.isModerator && !user.isAdmin"> + icon="pi pi-times-circle" (click)="onRowEditCancel(ri)" [disabled]="!user || !user.isModerator && !user.isAdmin">
diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index 4078a0be..70139bd4 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -280,7 +280,8 @@ "dashboard": "Dashboard", "levels": "Level", "members": "Mitglieder", - "profile": "Dein Profil" + "profile": "Dein Profil", + "achievements": "Errungenschaften" }, "server_empty": "Kein Server ausgewählt", "settings": "Einstellungen", -- 2.45.2 From 3507623c92aa123e2aa07cecbe73e8012efac1f5 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 12 Jul 2023 22:33:43 +0200 Subject: [PATCH 021/127] Improved achievement component #268_achievements --- kdb-web/package.json | 2 +- kdb-web/src/app/models/data/user.model.ts | 2 ++ .../components/achievement/achievement.component.html | 4 ++-- .../components/achievement/achievement.component.ts | 3 +++ kdb-web/src/assets/config.json | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/kdb-web/package.json b/kdb-web/package.json index e77d9ec0..70c9306f 100644 --- a/kdb-web/package.json +++ b/kdb-web/package.json @@ -1,6 +1,6 @@ { "name": "kdb-web", - "version": "1.0.7", + "version": "1.0.dev268_achievements", "scripts": { "ng": "ng", "update-version": "ts-node-esm update-version.ts", diff --git a/kdb-web/src/app/models/data/user.model.ts b/kdb-web/src/app/models/data/user.model.ts index fb36964e..0b054cc6 100644 --- a/kdb-web/src/app/models/data/user.model.ts +++ b/kdb-web/src/app/models/data/user.model.ts @@ -10,6 +10,8 @@ export interface User extends DataWithHistory { discordId?: number; name?: string; xp?: number; + message_count?: number; + reaction_count?: number; ontime?: number; level?: Level; server?: Server; diff --git a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html index 7bdfc233..2c080fd2 100644 --- a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html +++ b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html @@ -132,7 +132,7 @@ - + {{achievement.attribute}} @@ -143,7 +143,7 @@ - + {{achievement.operator}} 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 5eb90432..2836c8b7 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 @@ -60,6 +60,9 @@ export class AchievementComponent implements OnInit, OnDestroy { private server: Server = {}; public user: UserDTO | null = null; + public operators = ["==", "!=", "<=", ">=", "<", ">"]; + public attributes = ["xp", "message_count", "reaction_count", "ontime", "level"] + query: string = Queries.achievementWithHistoryQuery; public constructor( diff --git a/kdb-web/src/assets/config.json b/kdb-web/src/assets/config.json index 57eaafa7..a2d9a6c2 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": "7" + "Micro": "dev268_achievements" }, "Themes": [ { -- 2.45.2 From cab65477b099c853b57da4b958170a2b058ddf9d Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 12 Jul 2023 22:34:00 +0200 Subject: [PATCH 022/127] Improved achievement endpoint #268_achievements --- kdb-bot/src/bot_data/model/achievement.py | 4 ++++ kdb-bot/src/bot_graphql/model/user.gql | 2 ++ kdb-bot/src/bot_graphql/queries/user_query.py | 2 ++ 3 files changed, 8 insertions(+) diff --git a/kdb-bot/src/bot_data/model/achievement.py b/kdb-bot/src/bot_data/model/achievement.py index e01bafad..be78379e 100644 --- a/kdb-bot/src/bot_data/model/achievement.py +++ b/kdb-bot/src/bot_data/model/achievement.py @@ -21,6 +21,10 @@ class Achievement(TableABC): self._id = id self._name = name self._attribute = attribute + + if operator not in ["==", "!=", "<=", ">=", "<", ">"]: + raise ValueError("operator must be ==,!=,<=,>=,< or >") + self._operator = operator self._value = value self._server = server diff --git a/kdb-bot/src/bot_graphql/model/user.gql b/kdb-bot/src/bot_graphql/model/user.gql index e7f03f38..2925e223 100644 --- a/kdb-bot/src/bot_graphql/model/user.gql +++ b/kdb-bot/src/bot_graphql/model/user.gql @@ -3,6 +3,8 @@ type User implements TableWithHistoryQuery { discordId: String name: String xp: Int + messageCount: Int + reactionCount: Int ontime: Float level: Level diff --git a/kdb-bot/src/bot_graphql/queries/user_query.py b/kdb-bot/src/bot_graphql/queries/user_query.py index 9e924f5f..53c6a7c1 100644 --- a/kdb-bot/src/bot_graphql/queries/user_query.py +++ b/kdb-bot/src/bot_graphql/queries/user_query.py @@ -41,6 +41,8 @@ class UserQuery(DataQueryWithHistoryABC): self.set_field("discordId", self.resolve_discord_id) self.set_field("name", self.resolve_name) self.set_field("xp", self.resolve_xp) + self.set_field("messageCount", lambda x, *_: x.message_count) + self.set_field("reactionCount", lambda x, *_: x.reaction_count) self.set_field("ontime", self.resolve_ontime) self.set_field("level", self.resolve_level) self.add_collection( -- 2.45.2 From 184d2416951d242c24185886ce6c6c8813c7fb41 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 13 Jul 2023 13:54:13 +0200 Subject: [PATCH 023/127] Improved achievement logic #268_achievements --- kdb-bot/cpl-workspace.json | 1 + kdb-bot/src/bot/config | 2 +- kdb-bot/src/bot/startup_settings_extension.py | 6 +- kdb-bot/src/bot/translation/de.json | 3 + .../bot_core/configuration/bot_settings.py | 77 +++++++++------ .../bot_core/configuration/server_settings.py | 34 ++++--- .../abc/achievement_repository_abc.py | 13 +++ .../migration/achievements_migration.py | 21 +++- .../bot_data/model/user_got_achievement.py | 99 +++++++++++++++++++ .../achievements_repository_service.py | 38 +++++++ .../achievements/achievement_service.py | 78 +++++++++++++++ .../achievements/achievements_module.py | 6 +- .../modules/achievements/events/__init__.py | 1 + .../events/achievement_on_message_event.py | 43 ++++++++ .../configuration/level_server_settings.py | 28 ------ .../level/configuration/level_settings.py | 31 ------ .../modules/level/service/level_service.py | 6 +- 17 files changed, 375 insertions(+), 112 deletions(-) create mode 100644 kdb-bot/src/bot_data/model/user_got_achievement.py create mode 100644 kdb-bot/src/modules/achievements/achievement_service.py create mode 100644 kdb-bot/src/modules/achievements/events/__init__.py create mode 100644 kdb-bot/src/modules/achievements/events/achievement_on_message_event.py delete mode 100644 kdb-bot/src/modules/level/configuration/level_server_settings.py delete mode 100644 kdb-bot/src/modules/level/configuration/level_settings.py diff --git a/kdb-bot/cpl-workspace.json b/kdb-bot/cpl-workspace.json index 1e44549f..df40bb8b 100644 --- a/kdb-bot/cpl-workspace.json +++ b/kdb-bot/cpl-workspace.json @@ -7,6 +7,7 @@ "bot-core": "src/bot_core/bot-core.json", "bot-data": "src/bot_data/bot-data.json", "bot-graphql": "src/bot_graphql/bot-graphql.json", + "achievements": "src/modules/achievements/achievements.json", "auto-role": "src/modules/auto_role/auto-role.json", "base": "src/modules/base/base.json", "boot-log": "src/modules/boot_log/boot-log.json", diff --git a/kdb-bot/src/bot/config b/kdb-bot/src/bot/config index e1c1efac..35c9d4ec 160000 --- a/kdb-bot/src/bot/config +++ b/kdb-bot/src/bot/config @@ -1 +1 @@ -Subproject commit e1c1efac984a04826c0c2713a26129b9d34b21d6 +Subproject commit 35c9d4ecb4102b1b4ce758221d1efda25672e7e0 diff --git a/kdb-bot/src/bot/startup_settings_extension.py b/kdb-bot/src/bot/startup_settings_extension.py index 008ebd10..7a3dc599 100644 --- a/kdb-bot/src/bot/startup_settings_extension.py +++ b/kdb-bot/src/bot/startup_settings_extension.py @@ -11,7 +11,6 @@ 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.level.configuration.level_settings import LevelSettings from modules.permission.configuration.permission_settings import PermissionSettings @@ -37,7 +36,6 @@ class StartupSettingsExtension(StartupExtensionABC): 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, LevelSettings, lambda x: x.servers, lambda x: x.id) self._configure_settings_with_sub_settings( configuration, PermissionSettings, lambda x: x.servers, lambda x: x.id ) @@ -50,9 +48,9 @@ class StartupSettingsExtension(StartupExtensionABC): @staticmethod def _configure_settings_with_sub_settings( - config: ConfigurationABC, settings: Type, list_atr: Callable, atr: Callable + config: ConfigurationABC, settings_type: Type, list_atr: Callable, atr: Callable ): - settings: Optional[settings] = config.get_configuration(settings) + settings: Optional[settings_type] = config.get_configuration(settings_type) if settings is None: return diff --git a/kdb-bot/src/bot/translation/de.json b/kdb-bot/src/bot/translation/de.json index 4b6654d9..ca84b079 100644 --- a/kdb-bot/src/bot/translation/de.json +++ b/kdb-bot/src/bot/translation/de.json @@ -93,6 +93,9 @@ } }, "modules": { + "achievements": { + "got_new_achievement": "{} hat die Errungenschaft {} freigeschaltet :D" + }, "auto_role": { "add": { "error": { diff --git a/kdb-bot/src/bot_core/configuration/bot_settings.py b/kdb-bot/src/bot_core/configuration/bot_settings.py index 5fb5e0ee..dc6b8bbf 100644 --- a/kdb-bot/src/bot_core/configuration/bot_settings.py +++ b/kdb-bot/src/bot_core/configuration/bot_settings.py @@ -1,21 +1,30 @@ -import traceback - from cpl_core.configuration import ConfigurationModelABC -from cpl_core.console import Console 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): + 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) - self._technicians: List[int] = List(int) - self._wait_for_restart = 2 - self._wait_for_shutdown = 2 - self._cache_max_messages = 1000 + + if server_settings is not None: + self._servers_from_dict(server_settings) @property def servers(self) -> List[ServerSettings]: @@ -37,26 +46,34 @@ class BotSettings(ConfigurationModelABC): def cache_max_messages(self) -> int: return self._cache_max_messages - 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") + 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 - 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()}") + # 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/server_settings.py b/kdb-bot/src/bot_core/configuration/server_settings.py index 92b73d29..ca382886 100644 --- a/kdb-bot/src/bot_core/configuration/server_settings.py +++ b/kdb-bot/src/bot_core/configuration/server_settings.py @@ -1,15 +1,18 @@ -import traceback - from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console class ServerSettings(ConfigurationModelABC): - def __init__(self): + def __init__( + self, + id: int = None, + message_delete_timer: int = None, + notification_chat_id: int = None, + ): ConfigurationModelABC.__init__(self) - self._id: int = 0 - self._message_delete_timer: int = 0 + 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: @@ -19,10 +22,15 @@ class ServerSettings(ConfigurationModelABC): def message_delete_timer(self) -> int: return self._message_delete_timer - def from_dict(self, settings: dict): - try: - self._id = int(settings["Id"]) - self._message_delete_timer = int(settings["MessageDeleteTimer"]) - except Exception as e: - Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in settings") - Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}") + @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_data/abc/achievement_repository_abc.py b/kdb-bot/src/bot_data/abc/achievement_repository_abc.py index 4b817759..3850dc27 100644 --- a/kdb-bot/src/bot_data/abc/achievement_repository_abc.py +++ b/kdb-bot/src/bot_data/abc/achievement_repository_abc.py @@ -3,6 +3,7 @@ from abc import ABC, abstractmethod from cpl_query.extension import List from bot_data.model.achievement import Achievement +from bot_data.model.user_got_achievement import UserGotAchievement class AchievementRepositoryABC(ABC): @@ -22,6 +23,10 @@ class AchievementRepositoryABC(ABC): def get_achievements_by_server_id(self, server_id: int) -> List[Achievement]: pass + @abstractmethod + def get_achievements_by_user_id(self, user_id: int) -> List[Achievement]: + pass + @abstractmethod def add_achievement(self, achievement: Achievement): pass @@ -33,3 +38,11 @@ class AchievementRepositoryABC(ABC): @abstractmethod def delete_achievement(self, achievement: Achievement): pass + + @abstractmethod + def add_user_got_achievement(self, join: UserGotAchievement): + pass + + @abstractmethod + def delete_user_got_achievement(self, join: UserGotAchievement): + pass diff --git a/kdb-bot/src/bot_data/migration/achievements_migration.py b/kdb-bot/src/bot_data/migration/achievements_migration.py index 294d1b8b..1c453269 100644 --- a/kdb-bot/src/bot_data/migration/achievements_migration.py +++ b/kdb-bot/src/bot_data/migration/achievements_migration.py @@ -45,7 +45,7 @@ class AchievementsMigration(MigrationABC): `Attribute` VARCHAR(255) NOT NULL, `Operator` VARCHAR(2) NOT NULL, `Value` VARCHAR(255) NOT NULL, - `Deleted` BOOL DEFAULT FALSE, + `Deleted` BOOL DEFAULT FALSE, `DateFrom` DATETIME(6) NOT NULL, `DateTo` DATETIME(6) NOT NULL ); @@ -53,6 +53,25 @@ class AchievementsMigration(MigrationABC): ) ) + self._cursor.execute( + str( + f""" + CREATE TABLE IF NOT EXISTS `UserGotAchievements` ( + `Id` BIGINT NOT NULL AUTO_INCREMENT, + `UserId` BIGINT, + `AchievementId` BIGINT, + `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 (`UserId`) REFERENCES `Users`(`UserId`), + FOREIGN KEY (`AchievementId`) REFERENCES `Achievements`(`Id`) + ); + """ + ) + ) + + # A join table history between users and achievements is not necessary. + self._cursor.execute(str(f"""ALTER TABLE Users ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP;""")) self._cursor.execute(str(f"""ALTER TABLE Users ADD ReactionCount BIGINT NOT NULL DEFAULT 0 AFTER XP;""")) self._cursor.execute(str(f"""ALTER TABLE UsersHistory ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP;""")) diff --git a/kdb-bot/src/bot_data/model/user_got_achievement.py b/kdb-bot/src/bot_data/model/user_got_achievement.py new file mode 100644 index 00000000..3ca33d5d --- /dev/null +++ b/kdb-bot/src/bot_data/model/user_got_achievement.py @@ -0,0 +1,99 @@ +from datetime import datetime +from typing import Optional + +from cpl_core.database import TableABC + +from bot_data.model.achievement import Achievement +from bot_data.model.server import Server +from bot_data.model.user import User + + +class UserGotAchievement(TableABC): + def __init__( + self, + user: Optional[User], + achievement: Optional[Achievement], + server: Optional[Server], + created_at: datetime = None, + modified_at: datetime = None, + id=0, + ): + self._id = id + self._user = user + self._achievement = achievement + self._server = server + + 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 user(self) -> User: + return self._user + + @property + def achievement(self) -> Achievement: + return self._achievement + + @staticmethod + def get_select_all_string() -> str: + return str( + f""" + SELECT * FROM `UserGotAchievements`; + """ + ) + + @staticmethod + def get_select_by_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `UserGotAchievements` + WHERE `Id` = {id}; + """ + ) + + @staticmethod + def get_select_by_user_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `UserGotAchievements` + WHERE `UserId` = {id}; + """ + ) + + @property + def insert_string(self) -> str: + return str( + f""" + INSERT INTO `UserGotAchievements` ( + `UserId`, `AchievementId` + ) VALUES ( + {self._user.id}, + {self._achievement.id} + ); + """ + ) + + @property + def udpate_string(self) -> str: + return str( + f""" + UPDATE `UserGotAchievements` + SET `UserId` = '{self._user.id}', + `AchievementId` = '{self._achievement.id}' + WHERE `Id` = {self._id}; + """ + ) + + @property + def delete_string(self) -> str: + return str( + f""" + DELETE FROM `UserGotAchievements` + WHERE `Id` = {self._id}; + """ + ) diff --git a/kdb-bot/src/bot_data/service/achievements_repository_service.py b/kdb-bot/src/bot_data/service/achievements_repository_service.py index d9c157e2..da09786c 100644 --- a/kdb-bot/src/bot_data/service/achievements_repository_service.py +++ b/kdb-bot/src/bot_data/service/achievements_repository_service.py @@ -4,7 +4,9 @@ from cpl_query.extension import List from bot_core.logging.database_logger import DatabaseLogger from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.model.achievement import Achievement +from bot_data.model.user_got_achievement import UserGotAchievement class AchievementRepositoryService(AchievementRepositoryABC): @@ -13,11 +15,13 @@ class AchievementRepositoryService(AchievementRepositoryABC): logger: DatabaseLogger, db_context: DatabaseContextABC, servers: ServerRepositoryABC, + users: UserRepositoryABC, ): self._logger = logger self._context = db_context self._servers = servers + self._users = users AchievementRepositoryABC.__init__(self) @@ -33,6 +37,15 @@ class AchievementRepositoryService(AchievementRepositoryABC): id=result[0], ) + def _join_from_result(self, result: tuple): + return UserGotAchievement( + self._users.get_user_by_id(result[1]), + self.get_achievement_by_id(result[2]), + self._servers.get_server_by_id(result[3]), + result[5], + id=result[0], + ) + def get_achievements(self) -> List[Achievement]: achievements = List(Achievement) self._logger.trace(__name__, f"Send SQL command: {Achievement.get_select_all_string()}") @@ -59,6 +72,23 @@ class AchievementRepositoryService(AchievementRepositoryABC): return achievements + def get_achievements_by_user_id(self, user_id: int) -> List[Achievement]: + achievements = List(Achievement) + achievements_joins = List(UserGotAchievement) + self._logger.trace(__name__, f"Send SQL command: {UserGotAchievement.get_select_by_user_id_string(user_id)}") + results = self._context.select(UserGotAchievement.get_select_all_string()) + for result in results: + self._logger.trace(__name__, f"Got UserGotAchievement with id {result[0]}") + achievements_joins.append(self._join_from_result(result)) + + for achievements_join in achievements_joins: + results = self._context.select(Achievement.get_select_by_id_string(achievements_join.achievement.id)) + for result in results: + self._logger.trace(__name__, f"Got Achievement with id {result[0]}") + achievements.append(self._from_result(result)) + + return achievements + def add_achievement(self, achievement: Achievement): self._logger.trace(__name__, f"Send SQL command: {achievement.insert_string}") self._context.cursor.execute(achievement.insert_string) @@ -70,3 +100,11 @@ class AchievementRepositoryService(AchievementRepositoryABC): def delete_achievement(self, achievement: Achievement): self._logger.trace(__name__, f"Send SQL command: {achievement.delete_string}") self._context.cursor.execute(achievement.delete_string) + + def add_user_got_achievement(self, join: UserGotAchievement): + self._logger.trace(__name__, f"Send SQL command: {join.insert_string}") + self._context.cursor.execute(join.insert_string) + + def delete_user_got_achievement(self, join: UserGotAchievement): + self._logger.trace(__name__, f"Send SQL command: {join.delete_string}") + self._context.cursor.execute(join.delete_string) diff --git a/kdb-bot/src/modules/achievements/achievement_service.py b/kdb-bot/src/modules/achievements/achievement_service.py new file mode 100644 index 00000000..73e5ffe2 --- /dev/null +++ b/kdb-bot/src/modules/achievements/achievement_service.py @@ -0,0 +1,78 @@ +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 +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.model.achievement import Achievement +from bot_data.model.user import User +from bot_data.model.user_got_achievement import UserGotAchievement + + +class AchievementService: + def __init__( + self, + config: ConfigurationABC, + logger: LoggerABC, + bot: DiscordBotServiceABC, + achievements: AchievementRepositoryABC, + db: DatabaseContextABC, + message_service: MessageService, + t: TranslatePipe, + ): + self._config = config + self._logger = logger + self._bot = bot + self._achievements = achievements + self._db = db + self._message_service = message_service + self._t = t + + def _match(self, value: str, operator: str, expected_value: str) -> bool: + match operator: + case "==": + return value == expected_value + case "!=": + return value != expected_value + case "<=": + return value <= expected_value + case ">=": + return value >= expected_value + case "<": + return value < expected_value + case ">": + return value > expected_value + case _: + raise ValueError(f"Invalid operator: ${operator}") + + def has_user_achievement_already(self, user: User, achievement: Achievement) -> bool: + user_achievements = self._achievements.get_achievements_by_user_id(user.id) + return user_achievements.where(lambda x: x.name == achievement.name).count() > 0 + + def has_user_achievement(self, user: User, achievement: Achievement) -> bool: + return self._match(str(getattr(user, achievement.attribute)), achievement.operator, achievement.value) + + async def validate_achievements_for_user(self, user: User): + achievements = self._achievements.get_achievements_by_server_id(user.server.id) + for achievement in achievements: + if self.has_user_achievement_already(user, achievement) and not self.has_user_achievement( + user, achievement + ): + continue + + self._achievements.add_user_got_achievement(UserGotAchievement(user, achievement, user.server)) + self._db.save_changes() + await self._send_achievement_notification(user.server.discord_id, user.discord_id, achievement.name) + + 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}") + 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), + is_persistent=True, + ) diff --git a/kdb-bot/src/modules/achievements/achievements_module.py b/kdb-bot/src/modules/achievements/achievements_module.py index c3a7d5cd..3f70eaa5 100644 --- a/kdb-bot/src/modules/achievements/achievements_module.py +++ b/kdb-bot/src/modules/achievements/achievements_module.py @@ -1,10 +1,13 @@ 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.achievements.achievement_service import AchievementService +from modules.achievements.events.achievement_on_message_event import AchievementOnMessageEvent class AchievementsModule(ModuleABC): @@ -15,4 +18,5 @@ class AchievementsModule(ModuleABC): pass def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): - pass + services.add_transient(AchievementService) + self._dc.add_event(DiscordEventTypesEnum.on_message.value, AchievementOnMessageEvent) diff --git a/kdb-bot/src/modules/achievements/events/__init__.py b/kdb-bot/src/modules/achievements/events/__init__.py new file mode 100644 index 00000000..425ab6c1 --- /dev/null +++ b/kdb-bot/src/modules/achievements/events/__init__.py @@ -0,0 +1 @@ +# imports diff --git a/kdb-bot/src/modules/achievements/events/achievement_on_message_event.py b/kdb-bot/src/modules/achievements/events/achievement_on_message_event.py new file mode 100644 index 00000000..5b45cc5d --- /dev/null +++ b/kdb-bot/src/modules/achievements/events/achievement_on_message_event.py @@ -0,0 +1,43 @@ +import discord +from cpl_core.database.context import DatabaseContextABC +from cpl_core.logging import LoggerABC +from cpl_discord.events import OnMessageABC +from cpl_discord.service import DiscordBotServiceABC + +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.achievements.achievement_service import AchievementService + + +class AchievementOnMessageEvent(OnMessageABC): + def __init__( + self, + logger: LoggerABC, + bot: DiscordBotServiceABC, + achievements: AchievementService, + db: DatabaseContextABC, + servers: ServerRepositoryABC, + users: UserRepositoryABC, + ): + OnMessageABC.__init__(self) + + self._logger = logger + self._bot = bot + self._achievements = achievements + self._db = db + self._servers = servers + self._users = users + + @EventChecks.check_is_ready() + async def on_message(self, message: discord.Message): + if message.author.bot: + return + + server = self._servers.get_server_by_discord_id(message.guild.id) + user = self._users.get_user_by_discord_id_and_server_id(message.author.id, server.id) + + user.message_count += 1 + self._db.save_changes() + + await self._achievements.validate_achievements_for_user(user) diff --git a/kdb-bot/src/modules/level/configuration/level_server_settings.py b/kdb-bot/src/modules/level/configuration/level_server_settings.py deleted file mode 100644 index f6dce290..00000000 --- a/kdb-bot/src/modules/level/configuration/level_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 LevelServerSettings(ConfigurationModelABC): - def __init__(self): - ConfigurationModelABC.__init__(self) - - self._id: int = 0 - self._changed_level_notification_channel = 0 - - @property - def id(self) -> int: - return self._id - - @property - def changed_level_notification_channel(self) -> int: - return self._changed_level_notification_channel - - def from_dict(self, settings: dict): - try: - self._id = int(settings["Id"]) - self._changed_level_notification_channel = int(settings["ChangedLevelNotificationChannelId"]) - 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/configuration/level_settings.py b/kdb-bot/src/modules/level/configuration/level_settings.py deleted file mode 100644 index 7dd7db42..00000000 --- a/kdb-bot/src/modules/level/configuration/level_settings.py +++ /dev/null @@ -1,31 +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.level.configuration.level_server_settings import LevelServerSettings - - -class LevelSettings(ConfigurationModelABC): - def __init__(self): - ConfigurationModelABC.__init__(self) - - self._servers: List[LevelServerSettings] = List() - - @property - def servers(self) -> List[LevelServerSettings]: - return self._servers - - def from_dict(self, settings: dict): - try: - servers = List(LevelServerSettings) - for s in settings: - st = LevelServerSettings() - 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/level/service/level_service.py b/kdb-bot/src/modules/level/service/level_service.py index 412139ba..f4782592 100644 --- a/kdb-bot/src/modules/level/service/level_service.py +++ b/kdb-bot/src/modules/level/service/level_service.py @@ -6,13 +6,13 @@ 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 from bot_data.service.level_repository_service import LevelRepositoryService from bot_data.service.server_repository_service import ServerRepositoryService from bot_data.service.user_repository_service import UserRepositoryService -from modules.level.configuration.level_server_settings import LevelServerSettings class LevelService: @@ -75,9 +75,9 @@ class LevelService: self._logger.error(__name__, f"Adding role {level_role.name} to {member.name} failed!", e) if notification_needed: - level_settings: LevelServerSettings = self._config.get_configuration(f"LevelServerSettings_{guild.id}") + settings: ServerSettings = self._config.get_configuration(f"ServerSettings_{guild.id}") await self._message_service.send_channel_message( - self._bot.get_channel(level_settings.changed_level_notification_channel), + self._bot.get_channel(settings.notification_chat_id), self._t.transform("modules.level.new_level_message").format(member.mention, level.name), is_persistent=True, ) -- 2.45.2 From c8a2ed290baf648ec4028a3b7db0487d9a18e4f3 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sat, 15 Jul 2023 11:14:59 +0200 Subject: [PATCH 024/127] Fixed config #268_achievements --- kdb-bot/src/bot/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kdb-bot/src/bot/config b/kdb-bot/src/bot/config index 35c9d4ec..0179ab1e 160000 --- a/kdb-bot/src/bot/config +++ b/kdb-bot/src/bot/config @@ -1 +1 @@ -Subproject commit 35c9d4ecb4102b1b4ce758221d1efda25672e7e0 +Subproject commit 0179ab1ed725c233c5844ee94ed51cad176d9c7e -- 2.45.2 From cd5b3b6523f11c6e55659e915ab35b3c7b47920a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sat, 15 Jul 2023 12:52:54 +0200 Subject: [PATCH 025/127] Added logic to make achievement config more generic #268_achievements --- kdb-bot/src/bot_graphql/model/achievement.gql | 5 ++ kdb-bot/src/bot_graphql/model/query.gql | 2 + .../queries/achievement_attribute_query.py | 11 ++++ kdb-bot/src/bot_graphql/query.py | 4 ++ .../achievements/achievement_service.py | 13 ++++ .../modules/achievements/model/__init__.py | 1 + .../model/achievement_attribute.py | 20 +++++++ .../src/app/models/data/achievement.model.ts | 7 ++- .../src/app/models/graphql/queries.model.ts | 10 ++++ kdb-web/src/app/models/graphql/query.model.ts | 7 ++- .../achievement/achievement.component.html | 16 ++++- .../achievement/achievement.component.ts | 60 +++++++++++++++---- 12 files changed, 138 insertions(+), 18 deletions(-) create mode 100644 kdb-bot/src/bot_graphql/queries/achievement_attribute_query.py create mode 100644 kdb-bot/src/modules/achievements/model/__init__.py create mode 100644 kdb-bot/src/modules/achievements/model/achievement_attribute.py diff --git a/kdb-bot/src/bot_graphql/model/achievement.gql b/kdb-bot/src/bot_graphql/model/achievement.gql index 3a5f1328..ef124653 100644 --- a/kdb-bot/src/bot_graphql/model/achievement.gql +++ b/kdb-bot/src/bot_graphql/model/achievement.gql @@ -1,3 +1,8 @@ +type AchievementAttribute { + name: String + type: String +} + type Achievement implements TableWithHistoryQuery { id: ID name: String diff --git a/kdb-bot/src/bot_graphql/model/query.gql b/kdb-bot/src/bot_graphql/model/query.gql index 17d8634c..9f96dc61 100644 --- a/kdb-bot/src/bot_graphql/model/query.gql +++ b/kdb-bot/src/bot_graphql/model/query.gql @@ -31,6 +31,8 @@ type Query { achievementCount: Int achievements(filter: AchievementFilter, page: Page, sort: Sort): [Achievement] + AchievementAttributes: [AchievementAttribute] + AchievementOperators: [String] guilds(filter: GuildFilter): [Guild] } \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/queries/achievement_attribute_query.py b/kdb-bot/src/bot_graphql/queries/achievement_attribute_query.py new file mode 100644 index 00000000..2884c32b --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/achievement_attribute_query.py @@ -0,0 +1,11 @@ +from bot_graphql.abc.data_query_abc import DataQueryABC + + +class AchievementQuery(DataQueryABC): + def __init__( + self, + ): + DataQueryABC.__init__(self, "AchievementAttribute") + + self.set_field("name", lambda x, *_: x.name) + self.set_field("type", lambda x, *_: x.type) diff --git a/kdb-bot/src/bot_graphql/query.py b/kdb-bot/src/bot_graphql/query.py index 976b1950..8f3562ea 100644 --- a/kdb-bot/src/bot_graphql/query.py +++ b/kdb-bot/src/bot_graphql/query.py @@ -21,6 +21,7 @@ from bot_graphql.filter.user_filter import UserFilter from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter +from modules.achievements.achievement_service import AchievementService class Query(QueryABC): @@ -37,6 +38,7 @@ class Query(QueryABC): user_joined_game_server: UserJoinedGameServerRepositoryABC, users: UserRepositoryABC, achievements: AchievementRepositoryABC, + achievement_service: AchievementService, ): QueryABC.__init__(self, "Query") @@ -65,6 +67,8 @@ class Query(QueryABC): self.add_collection("achievement", lambda *_: achievements.get_achievements(), AchievementFilter) self.set_field("guilds", self._resolve_guilds) + self.set_field("AchievementAttributes", lambda x, *_: achievement_service.get_attributes()) + self.set_field("AchievementOperators", lambda x, *_: ["==", "!=", "<=", ">=", "<", ">"]) def _resolve_guilds(self, *_, filter=None): if filter is None or "id" not in filter: diff --git a/kdb-bot/src/modules/achievements/achievement_service.py b/kdb-bot/src/modules/achievements/achievement_service.py index 73e5ffe2..f767ef87 100644 --- a/kdb-bot/src/modules/achievements/achievement_service.py +++ b/kdb-bot/src/modules/achievements/achievement_service.py @@ -2,6 +2,7 @@ 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 +from cpl_query.extension import List from cpl_translation import TranslatePipe from bot_core.configuration.server_settings import ServerSettings @@ -10,6 +11,7 @@ from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC from bot_data.model.achievement import Achievement from bot_data.model.user import User from bot_data.model.user_got_achievement import UserGotAchievement +from modules.achievements.model.achievement_attribute import AchievementAttribute class AchievementService: @@ -31,6 +33,17 @@ class AchievementService: self._message_service = message_service self._t = t + def get_attributes(self) -> List[AchievementAttribute]: + attributes = List(AchievementAttribute) + + attributes.add(AchievementAttribute("xp", lambda user: user.xp, "number")) + attributes.add(AchievementAttribute("message_count", lambda user: user.message_count, "number")) + attributes.add(AchievementAttribute("reaction_count", lambda user: user.reaction_count, "number")) + attributes.add(AchievementAttribute("ontime", lambda user: user.ontime, "number")) + attributes.add(AchievementAttribute("level", lambda user: user.level, "Level")) + + return attributes + def _match(self, value: str, operator: str, expected_value: str) -> bool: match operator: case "==": diff --git a/kdb-bot/src/modules/achievements/model/__init__.py b/kdb-bot/src/modules/achievements/model/__init__.py new file mode 100644 index 00000000..425ab6c1 --- /dev/null +++ b/kdb-bot/src/modules/achievements/model/__init__.py @@ -0,0 +1 @@ +# imports diff --git a/kdb-bot/src/modules/achievements/model/achievement_attribute.py b/kdb-bot/src/modules/achievements/model/achievement_attribute.py new file mode 100644 index 00000000..c90d4722 --- /dev/null +++ b/kdb-bot/src/modules/achievements/model/achievement_attribute.py @@ -0,0 +1,20 @@ +from typing import Callable + + +class AchievementAttribute: + # frontend type = TypeScript types + def __init__(self, name: str, resolver: Callable, frontend_type: str): + self._name = name + self._resolver = resolver + self._frontend_type = frontend_type + + @property + def name(self) -> str: + return self._name + + @property + def type(self) -> str: + return self._frontend_type + + def resolve(self, *args, **kwargs): + return self._resolver(*args, **kwargs) diff --git a/kdb-web/src/app/models/data/achievement.model.ts b/kdb-web/src/app/models/data/achievement.model.ts index 0b1af096..23037847 100644 --- a/kdb-web/src/app/models/data/achievement.model.ts +++ b/kdb-web/src/app/models/data/achievement.model.ts @@ -1,10 +1,15 @@ import { DataWithHistory } from "./data.model"; import { Server, ServerFilter } from "./server.model"; +export interface AchievementAttribute { + name?: string; + type?: string; +} + export interface Achievement extends DataWithHistory { id?: number; name?: string; - attribute?: string; + attribute?: string | AchievementAttribute; operator?: string; value?: string; server?: Server; diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts index df3cf125..dafb897e 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -90,6 +90,16 @@ export class Queries { } `; + static achievementTypeQuery = ` + query AchievementType { + AchievementOperators + AchievementAttributes { + name + type + } + } + `; + static achievementQuery = ` query AchievementList($serverId: ID, $filter: AchievementFilter, $page: Page, $sort: Sort) { servers(filter: {id: $serverId}) { diff --git a/kdb-web/src/app/models/graphql/query.model.ts b/kdb-web/src/app/models/graphql/query.model.ts index 60e1964d..fe7ba7f9 100644 --- a/kdb-web/src/app/models/graphql/query.model.ts +++ b/kdb-web/src/app/models/graphql/query.model.ts @@ -3,7 +3,7 @@ import { User } from "../data/user.model"; import { AutoRole, AutoRoleRule } from "../data/auto_role.model"; import { Guild } from "../data/discord.model"; import { Level } from "../data/level.model"; -import { Achievement } from "../data/achievement.model"; +import { Achievement, AchievementAttribute } from "../data/achievement.model"; export interface Query { serverCount: number; @@ -24,6 +24,11 @@ export interface LevelListQuery { levels: Level[]; } +export interface AchievementTypeQuery { + AchievementAttributes: AchievementAttribute[]; + AchievementOperators: string[]; +} + export interface AchievementListQuery { achievementCount: number; achievements: Achievement[]; diff --git a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html index 2c080fd2..94b7e14a 100644 --- a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html +++ b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html @@ -132,7 +132,8 @@ - + {{achievement.attribute}} @@ -152,9 +153,18 @@ - + - + + + + {{achievement.value}} + + + + + + {{achievement.value}} 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 2836c8b7..3237048e 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 @@ -1,5 +1,5 @@ import { Component, OnDestroy, OnInit } from "@angular/core"; -import { Achievement, AchievementFilter } from "../../../../../../models/data/achievement.model"; +import { Achievement, AchievementAttribute, AchievementFilter } from "../../../../../../models/data/achievement.model"; import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; import { Page } from "../../../../../../models/graphql/filter/page.model"; import { Sort, SortDirection } from "../../../../../../models/graphql/filter/sort.model"; @@ -15,12 +15,12 @@ import { TranslateService } from "@ngx-translate/core"; import { DataService } from "../../../../../../services/data/data.service"; import { SidebarService } from "../../../../../../services/sidebar/sidebar.service"; import { ActivatedRoute } from "@angular/router"; -import { AchievementListQuery, Query } from "../../../../../../models/graphql/query.model"; +import { AchievementListQuery, AchievementTypeQuery, LevelListQuery, Query } from "../../../../../../models/graphql/query.model"; import { catchError, debounceTime, takeUntil } from "rxjs/operators"; -import { LazyLoadEvent } from "primeng/api"; +import { LazyLoadEvent, MenuItem } from "primeng/api"; import { Table } from "primeng/table"; import { User } from "../../../../../../models/data/user.model"; -import { AchievementMutationResult, UpdateUserMutationResult } from "../../../../../../models/graphql/result.model"; +import { AchievementMutationResult } from "../../../../../../models/graphql/result.model"; import { Mutations } from "../../../../../../models/graphql/mutations.model"; @Component({ @@ -60,8 +60,10 @@ export class AchievementComponent implements OnInit, OnDestroy { private server: Server = {}; public user: UserDTO | null = null; - public operators = ["==", "!=", "<=", ">=", "<", ">"]; - public attributes = ["xp", "message_count", "reaction_count", "ontime", "level"] + public operators: string[] = []; + public attributes: MenuItem[] = []; + private achievementsAttributes: AchievementAttribute[] = []; + levels!: MenuItem[]; query: string = Queries.achievementWithHistoryQuery; @@ -78,10 +80,10 @@ export class AchievementComponent implements OnInit, OnDestroy { } public ngOnInit(): void { + this.loading = true; this.setFilterForm(); this.data.getServerFromRoute(this.route).then(async server => { this.server = server; - this.loadNextPage(); let authUser = await this.authService.getLoggedInUser(); this.user = authUser?.users?.find(u => u.server == this.server.id) ?? null; }); @@ -92,8 +94,22 @@ export class AchievementComponent implements OnInit, OnDestroy { this.unsubscriber.complete(); } - public loadNextPage(): void { - this.loading = true; + + private loadLevels() { + this.data.query(Queries.levelQuery, { + serverId: this.server.id + }, + (data: Query) => { + return data.servers[0]; + } + ).subscribe(data => { + this.levels = data.levels.map(level => { + return { label: level.name, value: level.name }; + }); + }); + } + + private loadNextData() { this.data.query(Queries.achievementQuery, { serverId: this.server.id, filter: this.filter, page: this.page, sort: this.sort }, @@ -108,6 +124,19 @@ export class AchievementComponent implements OnInit, OnDestroy { }); } + public loadNextPage(): void { + this.data.query(Queries.achievementTypeQuery + ).subscribe(data => { + this.operators = data.AchievementOperators; + this.achievementsAttributes = data.AchievementAttributes; + this.attributes = data.AchievementAttributes.map(attribute => { + return { label: attribute.name, value: attribute.name }; + }); + this.loadLevels(); + this.loadNextData(); + }); + } + public setFilterForm(): void { this.filterForm = this.fb.group({ id: new FormControl(null), @@ -182,9 +211,9 @@ export class AchievementComponent implements OnInit, OnDestroy { this.spinner.showSpinner(); this.data.mutation(Mutations.createAchievement, { name: newAchievement.name, - attribute: newAchievement.attribute, - operator: newAchievement.operator, - value: newAchievement.value, + attribute: newAchievement.attribute, + operator: newAchievement.operator, + value: newAchievement.value + "", serverId: this.server.id } ).pipe(catchError(err => { @@ -207,7 +236,7 @@ export class AchievementComponent implements OnInit, OnDestroy { name: newAchievement.name, attribute: newAchievement.attribute, operator: newAchievement.operator, - value: newAchievement.value + value: newAchievement.value + "" } ).pipe(catchError(err => { this.spinner.hideSpinner(); @@ -268,4 +297,9 @@ export class AchievementComponent implements OnInit, OnDestroy { this.isEditingNew = true; } + + public getAchievementAttributeByName(name: string): AchievementAttribute { + const [found] = this.achievementsAttributes.filter(x => x.name === name); + return found; + } } -- 2.45.2 From 2293849d9498e2eb0a6c5839315ed37f9b78d9a3 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sat, 15 Jul 2023 13:16:13 +0200 Subject: [PATCH 026/127] Improved internal achievement checks #268_achievements --- kdb-bot/src/bot_data/db_context.py | 5 ++++ .../bot_data/model/user_got_achievement.py | 3 -- .../achievements_repository_service.py | 4 +-- .../achievements/achievement_service.py | 29 ++++++++++--------- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/kdb-bot/src/bot_data/db_context.py b/kdb-bot/src/bot_data/db_context.py index 46eff3bb..fb5e9f55 100644 --- a/kdb-bot/src/bot_data/db_context.py +++ b/kdb-bot/src/bot_data/db_context.py @@ -11,6 +11,7 @@ class DBContext(DatabaseContext): self._logger = logger DatabaseContext.__init__(self) + self._fails = 0 def connect(self, database_settings: DatabaseSettings): try: @@ -32,7 +33,11 @@ class DBContext(DatabaseContext): try: return super(DBContext, self).select(statement) except Exception as e: + if self._fails >= 3: + self._logger.fatal(__name__, f"Database error caused by {statement}", e) + self._logger.error(__name__, f"Database error caused by {statement}", e) + self._fails += 1 try: time.sleep(0.5) return self.select(statement) diff --git a/kdb-bot/src/bot_data/model/user_got_achievement.py b/kdb-bot/src/bot_data/model/user_got_achievement.py index 3ca33d5d..18bb6b92 100644 --- a/kdb-bot/src/bot_data/model/user_got_achievement.py +++ b/kdb-bot/src/bot_data/model/user_got_achievement.py @@ -4,7 +4,6 @@ from typing import Optional from cpl_core.database import TableABC from bot_data.model.achievement import Achievement -from bot_data.model.server import Server from bot_data.model.user import User @@ -13,7 +12,6 @@ class UserGotAchievement(TableABC): self, user: Optional[User], achievement: Optional[Achievement], - server: Optional[Server], created_at: datetime = None, modified_at: datetime = None, id=0, @@ -21,7 +19,6 @@ class UserGotAchievement(TableABC): self._id = id self._user = user self._achievement = achievement - self._server = server TableABC.__init__(self) self._created_at = created_at if created_at is not None else self._created_at diff --git a/kdb-bot/src/bot_data/service/achievements_repository_service.py b/kdb-bot/src/bot_data/service/achievements_repository_service.py index da09786c..6ee69abc 100644 --- a/kdb-bot/src/bot_data/service/achievements_repository_service.py +++ b/kdb-bot/src/bot_data/service/achievements_repository_service.py @@ -41,8 +41,8 @@ class AchievementRepositoryService(AchievementRepositoryABC): return UserGotAchievement( self._users.get_user_by_id(result[1]), self.get_achievement_by_id(result[2]), - self._servers.get_server_by_id(result[3]), - result[5], + result[3], + result[4], id=result[0], ) diff --git a/kdb-bot/src/modules/achievements/achievement_service.py b/kdb-bot/src/modules/achievements/achievement_service.py index f767ef87..23fb3754 100644 --- a/kdb-bot/src/modules/achievements/achievement_service.py +++ b/kdb-bot/src/modules/achievements/achievement_service.py @@ -33,16 +33,20 @@ class AchievementService: self._message_service = message_service self._t = t + self._attributes = List(AchievementAttribute) + + self._attributes.extend( + [ + AchievementAttribute("xp", lambda user: user.xp, "number"), + AchievementAttribute("message_count", lambda user: user.message_count, "number"), + AchievementAttribute("reaction_count", lambda user: user.reaction_count, "number"), + AchievementAttribute("ontime", lambda user: user.ontime, "number"), + AchievementAttribute("level", lambda user: user.level, "Level"), + ] + ) + def get_attributes(self) -> List[AchievementAttribute]: - attributes = List(AchievementAttribute) - - attributes.add(AchievementAttribute("xp", lambda user: user.xp, "number")) - attributes.add(AchievementAttribute("message_count", lambda user: user.message_count, "number")) - attributes.add(AchievementAttribute("reaction_count", lambda user: user.reaction_count, "number")) - attributes.add(AchievementAttribute("ontime", lambda user: user.ontime, "number")) - attributes.add(AchievementAttribute("level", lambda user: user.level, "Level")) - - return attributes + return self._attributes def _match(self, value: str, operator: str, expected_value: str) -> bool: match operator: @@ -66,14 +70,13 @@ class AchievementService: return user_achievements.where(lambda x: x.name == achievement.name).count() > 0 def has_user_achievement(self, user: User, achievement: Achievement) -> bool: - return self._match(str(getattr(user, achievement.attribute)), achievement.operator, achievement.value) + attribute: AchievementAttribute = self._attributes.where(lambda x: x.name == achievement.attribute).single() + return self._match(str(attribute.resolve(user)), achievement.operator, achievement.value) async def validate_achievements_for_user(self, user: User): achievements = self._achievements.get_achievements_by_server_id(user.server.id) for achievement in achievements: - if self.has_user_achievement_already(user, achievement) and not self.has_user_achievement( - user, achievement - ): + if self.has_user_achievement_already(user, achievement) or not self.has_user_achievement(user, achievement): continue self._achievements.add_user_got_achievement(UserGotAchievement(user, achievement, user.server)) -- 2.45.2 From 3fb951a748bf5905ff3e22a6446fbbc70fef5e3a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sat, 15 Jul 2023 13:38:10 +0200 Subject: [PATCH 027/127] Improved generic achievement logic #268_achievements --- .../achievement_attribute_resolver.py | 43 +++++++++++++++++++ .../achievements/achievement_service.py | 36 +++++++++------- 2 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 kdb-bot/src/modules/achievements/achievement_attribute_resolver.py diff --git a/kdb-bot/src/modules/achievements/achievement_attribute_resolver.py b/kdb-bot/src/modules/achievements/achievement_attribute_resolver.py new file mode 100644 index 00000000..9006da17 --- /dev/null +++ b/kdb-bot/src/modules/achievements/achievement_attribute_resolver.py @@ -0,0 +1,43 @@ +from typing import List + +from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC +from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC +from bot_data.abc.client_repository_abc import ClientRepositoryABC +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.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 +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.model.user import User + + +class AchievementAttributeResolver: + def __init__( + self, + auto_roles: AutoRoleRepositoryABC, + clients: ClientRepositoryABC, + known_users: KnownUserRepositoryABC, + levels: LevelRepositoryABC, + servers: ServerRepositoryABC, + user_joined_servers: UserJoinedServerRepositoryABC, + user_joined_voice_channels: UserJoinedVoiceChannelRepositoryABC, + user_joined_game_server: UserJoinedGameServerRepositoryABC, + users: UserRepositoryABC, + achievements: AchievementRepositoryABC, + ): + self._auto_roles = auto_roles + self._clients = clients + self._known_users = known_users + self._levels = levels + self._servers = servers + self._user_joined_servers = user_joined_servers + self._user_joined_voice_channels = user_joined_voice_channels + self._user_joined_game_server = user_joined_game_server + self._users = users + self._achievements = achievements + + def get_played_on_game_server(self, user: User) -> List[str]: + joins = self._user_joined_game_server.get_user_joined_game_servers_by_user_id(user.id) + return joins.select(lambda x: x.name) diff --git a/kdb-bot/src/modules/achievements/achievement_service.py b/kdb-bot/src/modules/achievements/achievement_service.py index 23fb3754..f6bf30ad 100644 --- a/kdb-bot/src/modules/achievements/achievement_service.py +++ b/kdb-bot/src/modules/achievements/achievement_service.py @@ -11,6 +11,7 @@ from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC from bot_data.model.achievement import Achievement 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 @@ -23,6 +24,7 @@ class AchievementService: achievements: AchievementRepositoryABC, db: DatabaseContextABC, message_service: MessageService, + resolver: AchievementAttributeResolver, t: TranslatePipe, ): self._config = config @@ -42,28 +44,32 @@ class AchievementService: AchievementAttribute("reaction_count", lambda user: user.reaction_count, "number"), AchievementAttribute("ontime", lambda user: user.ontime, "number"), AchievementAttribute("level", lambda user: user.level, "Level"), + # special cases + AchievementAttribute( + "played_on_game_server", lambda user: resolver.get_played_on_game_server(user), "GameServer" + ), + AchievementAttribute("last_single_ontime_hours", lambda user: user.level, "GameServer"), ] ) + self._operators = { + "==": lambda value, expected_value: value == expected_value, + "!=": lambda value, expected_value: value != expected_value, + "<=": lambda value, expected_value: value <= expected_value, + ">=": lambda value, expected_value: value >= expected_value, + "<": lambda value, expected_value: value < expected_value, + ">": lambda value, expected_value: value > expected_value, + "contains": lambda value, expected_value: expected_value in value, + } + + def get_operators(self) -> list[str]: + return [x for x in self._operators.keys()] + def get_attributes(self) -> List[AchievementAttribute]: return self._attributes def _match(self, value: str, operator: str, expected_value: str) -> bool: - match operator: - case "==": - return value == expected_value - case "!=": - return value != expected_value - case "<=": - return value <= expected_value - case ">=": - return value >= expected_value - case "<": - return value < expected_value - case ">": - return value > expected_value - case _: - raise ValueError(f"Invalid operator: ${operator}") + return self._operators[operator](value, expected_value) def has_user_achievement_already(self, user: User, achievement: Achievement) -> bool: user_achievements = self._achievements.get_achievements_by_user_id(user.id) -- 2.45.2 From 189128f0d30a0d475070ddf96777b13d9f1ba422 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sat, 15 Jul 2023 14:42:01 +0200 Subject: [PATCH 028/127] Added played_on_game_server achievement logic #268_achievements --- kdb-bot/src/bot/translation/de.json | 5 +- .../migration/achievements_migration.py | 4 +- kdb-bot/src/bot_data/model/achievement.py | 12 +++- kdb-bot/src/bot_graphql/graphql_module.py | 6 +- kdb-bot/src/bot_graphql/model/achievement.gql | 3 + kdb-bot/src/bot_graphql/model/query.gql | 7 ++- kdb-bot/src/bot_graphql/model/server.gql | 12 ++++ .../queries/achievement_attribute_query.py | 2 +- .../bot_graphql/queries/game_server_query.py | 10 ++++ .../src/bot_graphql/queries/server_query.py | 3 + kdb-bot/src/bot_graphql/query.py | 7 ++- .../achievement_attribute_resolver.py | 5 +- .../achievements/achievement_service.py | 4 +- .../achievements/achievements_module.py | 6 ++ .../modules/achievements/commands/__init__.py | 1 + .../commands/achievements_group.py | 57 +++++++++++++++++++ kdb-web/src/app/models/data/server.model.ts | 5 ++ .../src/app/models/graphql/queries.model.ts | 14 ++++- kdb-web/src/app/models/graphql/query.model.ts | 11 +++- .../achievement/achievement.component.html | 13 ++++- .../achievement/achievement.component.ts | 28 +++++++-- 21 files changed, 188 insertions(+), 27 deletions(-) create mode 100644 kdb-bot/src/bot_graphql/queries/game_server_query.py create mode 100644 kdb-bot/src/modules/achievements/commands/__init__.py create mode 100644 kdb-bot/src/modules/achievements/commands/achievements_group.py diff --git a/kdb-bot/src/bot/translation/de.json b/kdb-bot/src/bot/translation/de.json index ca84b079..27dd9749 100644 --- a/kdb-bot/src/bot/translation/de.json +++ b/kdb-bot/src/bot/translation/de.json @@ -94,7 +94,10 @@ }, "modules": { "achievements": { - "got_new_achievement": "{} hat die Errungenschaft {} freigeschaltet :D" + "got_new_achievement": "{} hat die Errungenschaft {} freigeschaltet :D", + "commands": { + "check": "Alles klar, ich schaue eben nach... nom nom" + } }, "auto_role": { "add": { diff --git a/kdb-bot/src/bot_data/migration/achievements_migration.py b/kdb-bot/src/bot_data/migration/achievements_migration.py index 1c453269..d9851cb5 100644 --- a/kdb-bot/src/bot_data/migration/achievements_migration.py +++ b/kdb-bot/src/bot_data/migration/achievements_migration.py @@ -22,7 +22,7 @@ class AchievementsMigration(MigrationABC): `Id` BIGINT NOT NULL AUTO_INCREMENT, `Name` VARCHAR(255) NOT NULL, `Attribute` VARCHAR(255) NOT NULL, - `Operator` VARCHAR(2) NOT NULL, + `Operator` VARCHAR(255) NOT NULL, `Value` VARCHAR(255) NOT NULL, `ServerId` BIGINT, `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6), @@ -43,7 +43,7 @@ class AchievementsMigration(MigrationABC): `ServerId` BIGINT, `Name` VARCHAR(255) NOT NULL, `Attribute` VARCHAR(255) NOT NULL, - `Operator` VARCHAR(2) NOT NULL, + `Operator` VARCHAR(255) NOT NULL, `Value` VARCHAR(255) NOT NULL, `Deleted` BOOL DEFAULT FALSE, `DateFrom` DATETIME(6) NOT NULL, diff --git a/kdb-bot/src/bot_data/model/achievement.py b/kdb-bot/src/bot_data/model/achievement.py index be78379e..9766710e 100644 --- a/kdb-bot/src/bot_data/model/achievement.py +++ b/kdb-bot/src/bot_data/model/achievement.py @@ -2,6 +2,7 @@ from datetime import datetime from typing import Optional from cpl_core.database import TableABC +from cpl_core.dependency_injection import ServiceProviderABC from bot_data.model.server import Server @@ -22,8 +23,8 @@ class Achievement(TableABC): self._name = name self._attribute = attribute - if operator not in ["==", "!=", "<=", ">=", "<", ">"]: - raise ValueError("operator must be ==,!=,<=,>=,< or >") + if self._is_operator_valid(operator): + raise ValueError("Operator invalid") self._operator = operator self._value = value @@ -33,6 +34,13 @@ class Achievement(TableABC): 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 + @ServiceProviderABC.inject + def _is_operator_valid(self, operator, service: ServiceProviderABC) -> bool: + from modules.achievements.achievement_service import AchievementService + + achievements: AchievementService = service.get_service(AchievementService) + return operator not in achievements.get_operators() + @property def id(self) -> int: return self._id diff --git a/kdb-bot/src/bot_graphql/graphql_module.py b/kdb-bot/src/bot_graphql/graphql_module.py index b861aec1..5e54b86d 100644 --- a/kdb-bot/src/bot_graphql/graphql_module.py +++ b/kdb-bot/src/bot_graphql/graphql_module.py @@ -26,6 +26,7 @@ from bot_graphql.mutations.auto_role_rule_mutation import AutoRoleRuleMutation from bot_graphql.mutations.level_mutation import LevelMutation 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 from bot_graphql.queries.achievement_query import AchievementQuery from bot_graphql.queries.auto_role_history_query import AutoRoleHistoryQuery from bot_graphql.queries.auto_role_query import AutoRoleQuery @@ -33,6 +34,7 @@ from bot_graphql.queries.auto_role_rule_history_query import AutoRoleRuleHistory from bot_graphql.queries.auto_role_rule_query import AutoRoleRuleQuery from bot_graphql.queries.client_history_query import ClientHistoryQuery from bot_graphql.queries.client_query import ClientQuery +from bot_graphql.queries.game_server_query import GameServerQuery 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 @@ -65,6 +67,8 @@ class GraphQLModule(ModuleABC): services.add_singleton(Mutation) # queries + services.add_transient(QueryABC, AchievementAttributeQuery) + services.add_transient(QueryABC, AchievementQuery) services.add_transient(QueryABC, AutoRoleHistoryQuery) services.add_transient(QueryABC, AutoRoleQuery) services.add_transient(QueryABC, AutoRoleRuleHistoryQuery) @@ -77,9 +81,9 @@ class GraphQLModule(ModuleABC): services.add_transient(QueryABC, LevelQuery) services.add_transient(QueryABC, ServerHistoryQuery) services.add_transient(QueryABC, ServerQuery) + services.add_transient(QueryABC, GameServerQuery) services.add_transient(QueryABC, UserHistoryQuery) services.add_transient(QueryABC, UserQuery) - services.add_transient(QueryABC, AchievementQuery) services.add_transient(QueryABC, UserJoinedServerHistoryQuery) services.add_transient(QueryABC, UserJoinedServerQuery) services.add_transient(QueryABC, UserJoinedVoiceChannelHistoryQuery) diff --git a/kdb-bot/src/bot_graphql/model/achievement.gql b/kdb-bot/src/bot_graphql/model/achievement.gql index ef124653..7cd86cf9 100644 --- a/kdb-bot/src/bot_graphql/model/achievement.gql +++ b/kdb-bot/src/bot_graphql/model/achievement.gql @@ -1,6 +1,9 @@ type AchievementAttribute { name: String type: String + + createdAt: String + modifiedAt: String } type Achievement implements TableWithHistoryQuery { diff --git a/kdb-bot/src/bot_graphql/model/query.gql b/kdb-bot/src/bot_graphql/model/query.gql index 9f96dc61..fefde64d 100644 --- a/kdb-bot/src/bot_graphql/model/query.gql +++ b/kdb-bot/src/bot_graphql/model/query.gql @@ -17,6 +17,9 @@ type Query { serverCount: Int servers(filter: ServerFilter, page: Page, sort: Sort): [Server] + gameServerCount: Int + gameServers: [GameServer] + userJoinedServerCount: Int userJoinedServers(filter: UserJoinedServerFilter, page: Page, sort: Sort): [UserJoinedServer] @@ -31,8 +34,8 @@ type Query { achievementCount: Int achievements(filter: AchievementFilter, page: Page, sort: Sort): [Achievement] - AchievementAttributes: [AchievementAttribute] - AchievementOperators: [String] + achievementAttributes: [AchievementAttribute] + achievementOperators: [String] 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 90f07f95..c4689ac9 100644 --- a/kdb-bot/src/bot_graphql/model/server.gql +++ b/kdb-bot/src/bot_graphql/model/server.gql @@ -1,3 +1,12 @@ +type GameServer { + id: ID + name: String + server: Server + + createdAt: String + modifiedAt: String +} + type Server implements TableWithHistoryQuery { id: ID discordId: String @@ -13,6 +22,9 @@ type Server implements TableWithHistoryQuery { levelCount: Int levels(filter: LevelFilter, page: Page, sort: Sort): [Level] + gameServerCount: Int + gameServers: [GameServer] + userCount: Int users(filter: UserFilter, page: Page, sort: Sort): [User] diff --git a/kdb-bot/src/bot_graphql/queries/achievement_attribute_query.py b/kdb-bot/src/bot_graphql/queries/achievement_attribute_query.py index 2884c32b..f9b77505 100644 --- a/kdb-bot/src/bot_graphql/queries/achievement_attribute_query.py +++ b/kdb-bot/src/bot_graphql/queries/achievement_attribute_query.py @@ -1,7 +1,7 @@ from bot_graphql.abc.data_query_abc import DataQueryABC -class AchievementQuery(DataQueryABC): +class AchievementAttributeQuery(DataQueryABC): def __init__( self, ): diff --git a/kdb-bot/src/bot_graphql/queries/game_server_query.py b/kdb-bot/src/bot_graphql/queries/game_server_query.py new file mode 100644 index 00000000..8b04b3b9 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/game_server_query.py @@ -0,0 +1,10 @@ +from bot_graphql.abc.data_query_abc import DataQueryABC + + +class GameServerQuery(DataQueryABC): + def __init__(self): + DataQueryABC.__init__(self, "GameServer") + + self.set_field("id", lambda x, *_: x.id) + self.set_field("name", lambda x, *_: x.name) + self.set_field("server", lambda x, *_: x.server) diff --git a/kdb-bot/src/bot_graphql/queries/server_query.py b/kdb-bot/src/bot_graphql/queries/server_query.py index 52d53d23..5da12f2d 100644 --- a/kdb-bot/src/bot_graphql/queries/server_query.py +++ b/kdb-bot/src/bot_graphql/queries/server_query.py @@ -4,6 +4,7 @@ from cpl_discord.service import DiscordBotServiceABC from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC 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.user_joined_server_repository_abc import UserJoinedServerRepositoryABC from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC @@ -26,6 +27,7 @@ class ServerQuery(DataQueryWithHistoryABC): auto_roles: AutoRoleRepositoryABC, clients: ClientRepositoryABC, levels: LevelRepositoryABC, + game_servers: GameServerRepositoryABC, users: UserRepositoryABC, ujs: UserJoinedServerRepositoryABC, ujvs: UserJoinedVoiceChannelRepositoryABC, @@ -56,6 +58,7 @@ class ServerQuery(DataQueryWithHistoryABC): ) self.add_collection("level", lambda server, *_: self._levels.get_levels_by_server_id(server.id), LevelFilter) self.add_collection("user", lambda server, *_: self._users.get_users_by_server_id(server.id), UserFilter) + self.add_collection("gameServer", lambda server, *_: game_servers.get_game_servers_by_server_id(server.id)) self.add_collection( "achievement", lambda server, *_: achievements.get_achievements_by_server_id(server.id), AchievementFilter ) diff --git a/kdb-bot/src/bot_graphql/query.py b/kdb-bot/src/bot_graphql/query.py index 8f3562ea..5c1d2263 100644 --- a/kdb-bot/src/bot_graphql/query.py +++ b/kdb-bot/src/bot_graphql/query.py @@ -3,6 +3,7 @@ from cpl_discord.service import DiscordBotServiceABC from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC 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.known_user_repository_abc import KnownUserRepositoryABC from bot_data.abc.level_repository_abc import LevelRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC @@ -33,6 +34,7 @@ class Query(QueryABC): known_users: KnownUserRepositoryABC, levels: LevelRepositoryABC, servers: ServerRepositoryABC, + game_servers: GameServerRepositoryABC, user_joined_servers: UserJoinedServerRepositoryABC, user_joined_voice_channels: UserJoinedVoiceChannelRepositoryABC, user_joined_game_server: UserJoinedGameServerRepositoryABC, @@ -50,6 +52,7 @@ class Query(QueryABC): self.add_collection("knownUser", lambda *_: known_users.get_users()) self.add_collection("level", lambda *_: levels.get_levels(), LevelFilter) self.add_collection("server", lambda *_: servers.get_servers(), ServerFilter) + self.add_collection("gameServer", lambda *_: game_servers.get_game_servers()) self.add_collection( "userJoinedServer", lambda *_: user_joined_servers.get_user_joined_servers(), UserJoinedServerFilter ) @@ -67,8 +70,8 @@ class Query(QueryABC): self.add_collection("achievement", lambda *_: achievements.get_achievements(), AchievementFilter) self.set_field("guilds", self._resolve_guilds) - self.set_field("AchievementAttributes", lambda x, *_: achievement_service.get_attributes()) - self.set_field("AchievementOperators", lambda x, *_: ["==", "!=", "<=", ">=", "<", ">"]) + self.set_field("achievementAttributes", lambda x, *_: achievement_service.get_attributes()) + self.set_field("achievementOperators", lambda x, *_: achievement_service.get_operators()) def _resolve_guilds(self, *_, filter=None): if filter is None or "id" not in filter: diff --git a/kdb-bot/src/modules/achievements/achievement_attribute_resolver.py b/kdb-bot/src/modules/achievements/achievement_attribute_resolver.py index 9006da17..4badad37 100644 --- a/kdb-bot/src/modules/achievements/achievement_attribute_resolver.py +++ b/kdb-bot/src/modules/achievements/achievement_attribute_resolver.py @@ -3,6 +3,7 @@ from typing import List from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC 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.known_user_repository_abc import KnownUserRepositoryABC from bot_data.abc.level_repository_abc import LevelRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC @@ -21,6 +22,7 @@ class AchievementAttributeResolver: known_users: KnownUserRepositoryABC, levels: LevelRepositoryABC, servers: ServerRepositoryABC, + game_servers: GameServerRepositoryABC, user_joined_servers: UserJoinedServerRepositoryABC, user_joined_voice_channels: UserJoinedVoiceChannelRepositoryABC, user_joined_game_server: UserJoinedGameServerRepositoryABC, @@ -32,6 +34,7 @@ class AchievementAttributeResolver: self._known_users = known_users self._levels = levels self._servers = servers + self._game_servers = game_servers self._user_joined_servers = user_joined_servers self._user_joined_voice_channels = user_joined_voice_channels self._user_joined_game_server = user_joined_game_server @@ -40,4 +43,4 @@ class AchievementAttributeResolver: def get_played_on_game_server(self, user: User) -> List[str]: joins = self._user_joined_game_server.get_user_joined_game_servers_by_user_id(user.id) - return joins.select(lambda x: x.name) + return joins.select(lambda x: x.game_server.name) diff --git a/kdb-bot/src/modules/achievements/achievement_service.py b/kdb-bot/src/modules/achievements/achievement_service.py index f6bf30ad..17486f80 100644 --- a/kdb-bot/src/modules/achievements/achievement_service.py +++ b/kdb-bot/src/modules/achievements/achievement_service.py @@ -68,7 +68,7 @@ class AchievementService: def get_attributes(self) -> List[AchievementAttribute]: return self._attributes - def _match(self, value: str, operator: str, expected_value: str) -> bool: + def _match(self, value: any, operator: str, expected_value: str) -> bool: return self._operators[operator](value, expected_value) def has_user_achievement_already(self, user: User, achievement: Achievement) -> bool: @@ -77,7 +77,7 @@ class AchievementService: def has_user_achievement(self, user: User, achievement: Achievement) -> bool: attribute: AchievementAttribute = self._attributes.where(lambda x: x.name == achievement.attribute).single() - return self._match(str(attribute.resolve(user)), achievement.operator, achievement.value) + return self._match(attribute.resolve(user), achievement.operator, achievement.value) async def validate_achievements_for_user(self, user: User): achievements = self._achievements.get_achievements_by_server_id(user.server.id) diff --git a/kdb-bot/src/modules/achievements/achievements_module.py b/kdb-bot/src/modules/achievements/achievements_module.py index 3f70eaa5..dc59af6c 100644 --- a/kdb-bot/src/modules/achievements/achievements_module.py +++ b/kdb-bot/src/modules/achievements/achievements_module.py @@ -6,7 +6,9 @@ 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.achievements.achievement_attribute_resolver import AchievementAttributeResolver from modules.achievements.achievement_service import AchievementService +from modules.achievements.commands.achievements_group import AchievementGroup from modules.achievements.events.achievement_on_message_event import AchievementOnMessageEvent @@ -18,5 +20,9 @@ class AchievementsModule(ModuleABC): pass def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): + services.add_transient(AchievementAttributeResolver) services.add_transient(AchievementService) + + self._dc.add_command(AchievementGroup) + self._dc.add_event(DiscordEventTypesEnum.on_message.value, AchievementOnMessageEvent) diff --git a/kdb-bot/src/modules/achievements/commands/__init__.py b/kdb-bot/src/modules/achievements/commands/__init__.py new file mode 100644 index 00000000..425ab6c1 --- /dev/null +++ b/kdb-bot/src/modules/achievements/commands/__init__.py @@ -0,0 +1 @@ +# imports diff --git a/kdb-bot/src/modules/achievements/commands/achievements_group.py b/kdb-bot/src/modules/achievements/commands/achievements_group.py new file mode 100644 index 00000000..189b8dae --- /dev/null +++ b/kdb-bot/src/modules/achievements/commands/achievements_group.py @@ -0,0 +1,57 @@ +import discord +from cpl_discord.command import DiscordCommandABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_translation import TranslatePipe +from discord.ext import commands +from discord.ext.commands import Context + +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 bot_data.abc.user_repository_abc import UserRepositoryABC +from modules.achievements.achievement_service import AchievementService + + +class AchievementGroup(DiscordCommandABC): + def __init__( + self, + logger: CommandLogger, + message_service: MessageServiceABC, + bot: DiscordBotServiceABC, + servers: ServerRepositoryABC, + users: UserRepositoryABC, + achievement_service: AchievementService, + translate: TranslatePipe, + ): + DiscordCommandABC.__init__(self) + + self._logger = logger + self._message_service = message_service + self._bot = bot + self._servers = servers + self._users = users + self._achievement_service = achievement_service + self._t = translate + + @commands.hybrid_group() + @commands.guild_only() + async def achievement(self, ctx: Context): + pass + + @achievement.command() + @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_moderator() + async def check(self, ctx: Context, member: discord.Member): + self._logger.debug(__name__, f"Received command achievement check {ctx}") + + server = self._servers.get_server_by_discord_id(member.guild.id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) + await self._message_service.send_ctx_msg( + ctx, + self._t.transform("modules.achievements.commands.check"), + ) + await self._achievement_service.validate_achievements_for_user(user) + + self._logger.trace(__name__, f"Finished command achievement check") diff --git a/kdb-web/src/app/models/data/server.model.ts b/kdb-web/src/app/models/data/server.model.ts index cc160e68..a045186d 100644 --- a/kdb-web/src/app/models/data/server.model.ts +++ b/kdb-web/src/app/models/data/server.model.ts @@ -4,6 +4,11 @@ import {Level} from "./level.model"; import {Client} from "./client.model"; import { AutoRole } from "./auto_role.model"; +export interface GameServer { + id?: number; + name?: string; +} + export interface Server extends Data { id?: number; discordId?: String; diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts index dafb897e..fd46191b 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -46,6 +46,16 @@ export class Queries { } `; + static gameServerQuery = ` + query GameServersList($serverId: ID) { + servers(filter: {id: $serverId}) { + gameServers { + name + } + } + } + ` + static levelQuery = ` query LevelsList($serverId: ID, $filter: LevelFilter, $page: Page, $sort: Sort) { servers(filter: {id: $serverId}) { @@ -92,8 +102,8 @@ export class Queries { static achievementTypeQuery = ` query AchievementType { - AchievementOperators - AchievementAttributes { + achievementOperators + achievementAttributes { name type } diff --git a/kdb-web/src/app/models/graphql/query.model.ts b/kdb-web/src/app/models/graphql/query.model.ts index fe7ba7f9..92c54ae7 100644 --- a/kdb-web/src/app/models/graphql/query.model.ts +++ b/kdb-web/src/app/models/graphql/query.model.ts @@ -1,4 +1,4 @@ -import { Server } from "../data/server.model"; +import { GameServer, Server } from "../data/server.model"; import { User } from "../data/user.model"; import { AutoRole, AutoRoleRule } from "../data/auto_role.model"; import { Guild } from "../data/discord.model"; @@ -19,14 +19,19 @@ export interface UserListQuery { users: User[]; } +export interface GameServerListQuery { + gameServerCount: number; + gameServers: GameServer[]; +} + export interface LevelListQuery { levelCount: number; levels: Level[]; } export interface AchievementTypeQuery { - AchievementAttributes: AchievementAttribute[]; - AchievementOperators: string[]; + achievementAttributes: AchievementAttribute[]; + achievementOperators: string[]; } export interface AchievementListQuery { diff --git a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html index 94b7e14a..e9ceeb2a 100644 --- a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html +++ b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html @@ -153,7 +153,7 @@ - + @@ -162,7 +162,7 @@ - + @@ -170,6 +170,15 @@ {{achievement.value}} + + + + + + + {{achievement.value}} + + 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 3237048e..13d18fe7 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 @@ -15,7 +15,7 @@ import { TranslateService } from "@ngx-translate/core"; import { DataService } from "../../../../../../services/data/data.service"; import { SidebarService } from "../../../../../../services/sidebar/sidebar.service"; import { ActivatedRoute } from "@angular/router"; -import { AchievementListQuery, AchievementTypeQuery, LevelListQuery, Query } from "../../../../../../models/graphql/query.model"; +import { AchievementListQuery, AchievementTypeQuery, GameServerListQuery, LevelListQuery, Query } from "../../../../../../models/graphql/query.model"; import { catchError, debounceTime, takeUntil } from "rxjs/operators"; import { LazyLoadEvent, MenuItem } from "primeng/api"; import { Table } from "primeng/table"; @@ -63,7 +63,9 @@ export class AchievementComponent implements OnInit, OnDestroy { public operators: string[] = []; public attributes: MenuItem[] = []; private achievementsAttributes: AchievementAttribute[] = []; - levels!: MenuItem[]; + + public levels!: MenuItem[]; + public gameServers!: MenuItem[]; query: string = Queries.achievementWithHistoryQuery; @@ -94,7 +96,6 @@ export class AchievementComponent implements OnInit, OnDestroy { this.unsubscriber.complete(); } - private loadLevels() { this.data.query(Queries.levelQuery, { serverId: this.server.id @@ -109,6 +110,20 @@ export class AchievementComponent implements OnInit, OnDestroy { }); } + private loadGameServers() { + this.data.query(Queries.gameServerQuery, { + serverId: this.server.id + }, + (data: Query) => { + return data.servers[0]; + } + ).subscribe(data => { + this.gameServers = data.gameServers.map(gameServer => { + return { label: gameServer.name, value: gameServer.name }; + }); + }); + } + private loadNextData() { this.data.query(Queries.achievementQuery, { serverId: this.server.id, filter: this.filter, page: this.page, sort: this.sort @@ -127,12 +142,13 @@ export class AchievementComponent implements OnInit, OnDestroy { public loadNextPage(): void { this.data.query(Queries.achievementTypeQuery ).subscribe(data => { - this.operators = data.AchievementOperators; - this.achievementsAttributes = data.AchievementAttributes; - this.attributes = data.AchievementAttributes.map(attribute => { + this.operators = data.achievementOperators; + this.achievementsAttributes = data.achievementAttributes; + this.attributes = data.achievementAttributes.map(attribute => { return { label: attribute.name, value: attribute.name }; }); this.loadLevels(); + this.loadGameServers(); this.loadNextData(); }); } -- 2.45.2 From a71e3e472081187ea633c02d3866e11e3a89dc71 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sat, 15 Jul 2023 14:48:04 +0200 Subject: [PATCH 029/127] Added last_single_ontime_hours achievement logic #268_achievements --- .../modules/achievements/achievement_attribute_resolver.py | 4 ++++ kdb-bot/src/modules/achievements/achievement_service.py | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/kdb-bot/src/modules/achievements/achievement_attribute_resolver.py b/kdb-bot/src/modules/achievements/achievement_attribute_resolver.py index 4badad37..f08f1579 100644 --- a/kdb-bot/src/modules/achievements/achievement_attribute_resolver.py +++ b/kdb-bot/src/modules/achievements/achievement_attribute_resolver.py @@ -44,3 +44,7 @@ class AchievementAttributeResolver: def get_played_on_game_server(self, user: User) -> List[str]: joins = self._user_joined_game_server.get_user_joined_game_servers_by_user_id(user.id) return joins.select(lambda x: x.game_server.name) + + def get_last_ontime_hours(self, user: User) -> int: + ujvs = self._user_joined_voice_channels.get_user_joined_voice_channels_by_user_id(user.id) + return int(str(ujvs.max(lambda join: (join.leaved_on - join.joined_on).total_seconds() / 3600))) diff --git a/kdb-bot/src/modules/achievements/achievement_service.py b/kdb-bot/src/modules/achievements/achievement_service.py index 17486f80..b446d095 100644 --- a/kdb-bot/src/modules/achievements/achievement_service.py +++ b/kdb-bot/src/modules/achievements/achievement_service.py @@ -48,7 +48,9 @@ class AchievementService: AchievementAttribute( "played_on_game_server", lambda user: resolver.get_played_on_game_server(user), "GameServer" ), - AchievementAttribute("last_single_ontime_hours", lambda user: user.level, "GameServer"), + AchievementAttribute( + "last_single_ontime_hours", lambda user: resolver.get_last_ontime_hours(user), "number" + ), ] ) @@ -62,6 +64,9 @@ class AchievementService: "contains": lambda value, expected_value: expected_value in value, } + def add_achievement_attribute(self, atr: AchievementAttribute): + self._attributes.add(atr) + def get_operators(self) -> list[str]: return [x for x in self._operators.keys()] -- 2.45.2 From aae6472e114031736eace2205fbef9b38797b11d Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sat, 15 Jul 2023 15:16:01 +0200 Subject: [PATCH 030/127] Added achievements to user profile #268_achievements --- .../achievements_repository_service.py | 2 +- kdb-bot/src/bot_graphql/model/user.gql | 3 + kdb-bot/src/bot_graphql/queries/user_query.py | 8 +++ .../src/app/models/data/achievement.model.ts | 2 + kdb-web/src/app/models/data/user.model.ts | 4 ++ .../src/app/models/graphql/queries.model.ts | 6 ++ .../server/profile/profile.component.html | 35 ++++++++-- kdb-web/src/assets/i18n/de.json | 65 ++++++++++--------- kdb-web/src/assets/i18n/en.json | 36 +++++++++- 9 files changed, 121 insertions(+), 40 deletions(-) diff --git a/kdb-bot/src/bot_data/service/achievements_repository_service.py b/kdb-bot/src/bot_data/service/achievements_repository_service.py index 6ee69abc..130da9c8 100644 --- a/kdb-bot/src/bot_data/service/achievements_repository_service.py +++ b/kdb-bot/src/bot_data/service/achievements_repository_service.py @@ -76,7 +76,7 @@ class AchievementRepositoryService(AchievementRepositoryABC): achievements = List(Achievement) achievements_joins = List(UserGotAchievement) self._logger.trace(__name__, f"Send SQL command: {UserGotAchievement.get_select_by_user_id_string(user_id)}") - results = self._context.select(UserGotAchievement.get_select_all_string()) + results = self._context.select(UserGotAchievement.get_select_by_user_id_string(user_id)) for result in results: self._logger.trace(__name__, f"Got UserGotAchievement with id {result[0]}") achievements_joins.append(self._join_from_result(result)) diff --git a/kdb-bot/src/bot_graphql/model/user.gql b/kdb-bot/src/bot_graphql/model/user.gql index 2925e223..38db3573 100644 --- a/kdb-bot/src/bot_graphql/model/user.gql +++ b/kdb-bot/src/bot_graphql/model/user.gql @@ -17,6 +17,9 @@ type User implements TableWithHistoryQuery { userJoinedGameServerCount: Int userJoinedGameServers(filter: UserJoinedGameServerFilter, page: Page, sort: Sort): [UserJoinedGameServer] + achievementCount: Int + achievements(filter: AchievementFilter, page: Page, sort: Sort): [Achievement] + server: Server leftServer: Boolean diff --git a/kdb-bot/src/bot_graphql/queries/user_query.py b/kdb-bot/src/bot_graphql/queries/user_query.py index 53c6a7c1..9bb4a48b 100644 --- a/kdb-bot/src/bot_graphql/queries/user_query.py +++ b/kdb-bot/src/bot_graphql/queries/user_query.py @@ -2,12 +2,14 @@ from cpl_core.database.context import DatabaseContextABC from cpl_discord.service import DiscordBotServiceABC from bot_core.abc.client_utils_abc import ClientUtilsABC +from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC 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 from bot_data.model.user import User from bot_data.model.user_history import UserHistory from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC +from bot_graphql.filter.achievement_filter import AchievementFilter from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter @@ -26,6 +28,7 @@ class UserQuery(DataQueryWithHistoryABC): ujvs: UserJoinedVoiceChannelRepositoryABC, user_joined_game_server: UserJoinedGameServerRepositoryABC, permissions: PermissionServiceABC, + achievements: AchievementRepositoryABC, ): DataQueryWithHistoryABC.__init__(self, "User", "UsersHistory", UserHistory, db) @@ -36,6 +39,7 @@ class UserQuery(DataQueryWithHistoryABC): self._ujs = ujs self._ujvs = ujvs self._permissions = permissions + self._achievements = achievements self.set_field("id", self.resolve_id) self.set_field("discordId", self.resolve_discord_id) @@ -60,6 +64,10 @@ class UserQuery(DataQueryWithHistoryABC): lambda user, *_: self._user_joined_game_server.get_user_joined_game_servers_by_user_id(user.id), UserJoinedGameServerFilter, ) + self.add_collection( + "achievement", lambda user, *_: achievements.get_achievements_by_user_id(user.id), AchievementFilter + ) + self.set_field("server", self.resolve_server) self.set_field("leftServer", self.resolve_left_server) diff --git a/kdb-web/src/app/models/data/achievement.model.ts b/kdb-web/src/app/models/data/achievement.model.ts index 23037847..84f6f88e 100644 --- a/kdb-web/src/app/models/data/achievement.model.ts +++ b/kdb-web/src/app/models/data/achievement.model.ts @@ -13,6 +13,8 @@ export interface Achievement extends DataWithHistory { operator?: string; value?: string; server?: Server; + + createdAt?: string; } export interface AchievementFilter { diff --git a/kdb-web/src/app/models/data/user.model.ts b/kdb-web/src/app/models/data/user.model.ts index 0b054cc6..6d649da4 100644 --- a/kdb-web/src/app/models/data/user.model.ts +++ b/kdb-web/src/app/models/data/user.model.ts @@ -4,6 +4,7 @@ import { Server, ServerFilter } from "./server.model"; import { UserJoinedServer } from "./user_joined_server.model"; import { UserJoinedVoiceChannel } from "./user_joined_voice_channel.model"; import { UserJoinedGameServer } from "./user_joined_game_server.model"; +import { Achievement } from "./achievement.model"; export interface User extends DataWithHistory { id?: number; @@ -25,6 +26,9 @@ export interface User extends DataWithHistory { userJoinedGameServerCount?: number; userJoinedGameServers?: UserJoinedGameServer[]; + + achievementCount?: number; + achievements?: Achievement[]; } export interface UserFilter { diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts index fd46191b..453b7b64 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -222,6 +222,12 @@ export class Queries { joinedOn leavedOn } + + achievements { + id + name + createdAt + } } } } diff --git a/kdb-web/src/app/modules/view/server/profile/profile.component.html b/kdb-web/src/app/modules/view/server/profile/profile.component.html index 05d3ccc5..175be4ae 100644 --- a/kdb-web/src/app/modules/view/server/profile/profile.component.html +++ b/kdb-web/src/app/modules/view/server/profile/profile.component.html @@ -41,12 +41,12 @@ - - - - - - + + + + + +
@@ -78,6 +78,27 @@
+ +
+
+
+
{{'common.name' | translate}}:
+
{{achievement.name}}
+
+ +
+
{{'common.name' | translate}}:
+
{{achievement.name}}
+
+ +
+
{{'view.server.profile.achievements.time' | translate}}:
+
{{achievement.createdAt | date:'dd.MM.yyyy HH:mm:ss'}}
+
+
+
+
+
@@ -102,8 +123,8 @@
- +
diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index 70139bd4..6bcc1328 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -97,6 +97,7 @@ "wrong_password": "Falsches Passwort" }, "register": { + "confirm_privacy": "Ich erkläre mich mit der Datenschutzerklärung einverstanden.", "email_required": "E-Mail benötigt", "emails_not_match": "E-Mails stimmen nicht überein", "first_name": "Vorname", @@ -113,8 +114,7 @@ "register_with_discord": "Mit Discord Registrieren", "repeat_email": "E-Mail wiederholen", "repeat_password": "Passwort wiederholen", - "user_already_exists": "Benutzer existiert bereits", - "confirm_privacy": "Ich erkläre mich mit der Datenschutzerklärung einverstanden." + "user_already_exists": "Benutzer existiert bereits" } }, "common": { @@ -153,6 +153,7 @@ "joined_at": "Beigetreten am", "leaved_at": "Verlassen am", "modified_at": "Bearbeitet am", + "name": "Name", "no_entries_found": "Keine Einträge gefunden", "of": "von", "reset_filters": "Filter zurücksetzen" @@ -276,12 +277,12 @@ "dashboard": "Dashboard", "members": "Mitglieder", "server": { + "achievements": "Errungenschaften", "auto_roles": "Auto Rollen", "dashboard": "Dashboard", "levels": "Level", "members": "Mitglieder", - "profile": "Dein Profil", - "achievements": "Errungenschaften" + "profile": "Dein Profil" }, "server_empty": "Kein Server ausgewählt", "settings": "Einstellungen", @@ -316,6 +317,32 @@ "servers": "Server" }, "server": { + "achievements": { + "achievements": "Errungenschaften", + "header": "Errungenschaften", + "headers": { + "attribute": "Attribut", + "name": "Name", + "operator": "Operator", + "value": "Wert" + }, + "message": { + "achievement_create": "Errungenschaft erstellt", + "achievement_create_d": "Errungenschaft {{name}} erfolgreich erstellt", + "achievement_create_failed": "Errungenschaft Erstellung fehlgeschlagen", + "achievement_create_failed_d": "Die Erstellung der Errungenschaft ist fehlgeschlagen!", + "achievement_delete": "Errungenschaft löschen", + "achievement_delete_failed": "Errungenschaft Löschung fehlgeschlagen", + "achievement_delete_failed_d": "Die Löschung der Errungenschaft {{name}} ist fehlgeschlagen!", + "achievement_delete_q": "Sind Sie sich sicher, dass Sie das Errungenschaft {{name}} löschen möchten?", + "achievement_deleted": "Errungenschaft gelöscht", + "achievement_deleted_d": "Errungenschaft {{name}} erfolgreich gelöscht", + "achievement_update": "Errungenschaft bearbeitet", + "achievement_update_d": "Errungenschaft {{name}} erfolgreich bearbeitet", + "achievement_update_failed": "Errungenschaft Bearbeitung fehlgeschlagen", + "achievement_update_failed_d": "Die Bearbeitung der Errungenschaft ist fehlgeschlagen!" + } + }, "auto_roles": { "auto_roles": "Auto Rollen", "header": "Auto Rollen", @@ -398,32 +425,6 @@ "level_update_failed_d": "Die Bearbeitung des Levels ist fehlgeschlagen!" } }, - "achievements": { - "header": "Errungenschaften", - "headers": { - "name": "Name", - "attribute": "Attribut", - "operator": "Operator", - "value": "Wert" - }, - "achievements": "Errungenschaften", - "message": { - "achievement_create": "Errungenschaft erstellt", - "achievement_create_d": "Errungenschaft {{name}} erfolgreich erstellt", - "achievement_create_failed": "Errungenschaft Erstellung fehlgeschlagen", - "achievement_create_failed_d": "Die Erstellung der Errungenschaft ist fehlgeschlagen!", - "achievement_delete": "Errungenschaft löschen", - "achievement_delete_failed": "Errungenschaft Löschung fehlgeschlagen", - "achievement_delete_failed_d": "Die Löschung der Errungenschaft {{name}} ist fehlgeschlagen!", - "achievement_delete_q": "Sind Sie sich sicher, dass Sie das Errungenschaft {{name}} löschen möchten?", - "achievement_deleted": "Errungenschaft gelöscht", - "achievement_deleted_d": "Errungenschaft {{name}} erfolgreich gelöscht", - "achievement_update": "Errungenschaft bearbeitet", - "achievement_update_d": "Errungenschaft {{name}} erfolgreich bearbeitet", - "achievement_update_failed": "Errungenschaft Bearbeitung fehlgeschlagen", - "achievement_update_failed_d": "Die Bearbeitung der Errungenschaft ist fehlgeschlagen!" - } - }, "members": { "header": "Mitglieder", "headers": { @@ -442,6 +443,10 @@ } }, "profile": { + "achievements": { + "header": "Errungeschaften", + "time": "Erreicht am" + }, "header": "Dein Profil", "joined_game_server": { "header": "Gameserver-beitritte", diff --git a/kdb-web/src/assets/i18n/en.json b/kdb-web/src/assets/i18n/en.json index 62a3f623..862fcf4a 100644 --- a/kdb-web/src/assets/i18n/en.json +++ b/kdb-web/src/assets/i18n/en.json @@ -97,6 +97,7 @@ "wrong_password": "Wrong password" }, "register": { + "confirm_privacy": "I agree to the Privacy Policy.", "email_required": "E-Mail required", "emails_not_match": "E-Mails do not match", "first_name": "First name", @@ -113,8 +114,7 @@ "register_with_discord": "Register with discord", "repeat_email": "Repeat E-mail", "repeat_password": "Repeat password", - "user_already_exists": "User already exists", - "confirm_privacy": "I agree to the Privacy Policy." + "user_already_exists": "User already exists" } }, "common": { @@ -153,6 +153,7 @@ "joined_at": "Joined at", "leaved_at": "Leaved at", "modified_at": "Modified at", + "name": "Name", "no_entries_found": "No entries found", "of": "of", "reset_filters": "Reset filters" @@ -276,6 +277,7 @@ "dashboard": "Dashboard", "members": "Members", "server": { + "achievements": "Achievements", "auto_roles": "Auto role", "dashboard": "Dashboard", "levels": "Level", @@ -315,6 +317,32 @@ "servers": "Server" }, "server": { + "achievements": { + "achievements": "Achievements", + "header": "Achievements", + "headers": { + "attribute": "Attribute", + "name": "Namer", + "operator": "Operator", + "value": "Value" + }, + "message": { + "achievement_create": "Achievement created", + "achievement_create_d": "Achievement {{name}} successfully created", + "achievement_create_failed": "Achievement creation failed", + "achievement_create_failed_d": "Creation of achievement failed!", + "achievement_delete": "Delete achievement", + "achievement_delete_failed": "Achievement deletion failed", + "achievement_delete_failed_d": "Deletion of achievement {{name}} failed!", + "achievement_delete_q": "Are you sure you want to delete the {{name}} achievement?", + "achievement_deleted": "Achievement deleted", + "achievement_deleted_d": "Achievement {{name}} successfully deleted\t", + "achievement_update": "Achievement edited", + "achievement_update_d": "Achievement {{name}} edited successfully", + "achievement_update_failed": "Achievement editing failed", + "achievement_update_failed_d": "Achievement editing failed!" + } + }, "auto_roles": { "auto_roles": "Auto roles", "header": "Auto roles", @@ -415,6 +443,10 @@ } }, "profile": { + "achievements": { + "header": "Achievements", + "time": "Reached at" + }, "header": "Profile", "joined_game_server": { "header": "Game server accessions", -- 2.45.2 From eb3715d00b4649132f67d288ebbb9d7ccf32729b Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sat, 15 Jul 2023 15:16:54 +0200 Subject: [PATCH 031/127] Fixed achievements in user profile #268_achievements --- .../app/modules/view/server/profile/profile.component.html | 5 ----- 1 file changed, 5 deletions(-) diff --git a/kdb-web/src/app/modules/view/server/profile/profile.component.html b/kdb-web/src/app/modules/view/server/profile/profile.component.html index 175be4ae..28de57cb 100644 --- a/kdb-web/src/app/modules/view/server/profile/profile.component.html +++ b/kdb-web/src/app/modules/view/server/profile/profile.component.html @@ -86,11 +86,6 @@
{{achievement.name}}
-
-
{{'common.name' | translate}}:
-
{{achievement.name}}
-
-
{{'view.server.profile.achievements.time' | translate}}:
{{achievement.createdAt | date:'dd.MM.yyyy HH:mm:ss'}}
-- 2.45.2 From f7297ddf789f7a796be13040a36c25e0539e6eeb Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sat, 15 Jul 2023 15:47:40 +0200 Subject: [PATCH 032/127] Added history for achievements to frontend #268_achievements --- .../migration/achievements_migration.py | 2 +- .../src/bot_data/model/achievement_history.py | 26 +++++-------------- kdb-bot/src/bot_data/model/user_history.py | 12 +++++++++ kdb-bot/src/bot_graphql/graphql_module.py | 2 ++ kdb-bot/src/bot_graphql/model/achievement.gql | 2 +- .../queries/achievement_history_query.py | 13 ++++++++++ .../bot_graphql/queries/achievement_query.py | 4 +-- kdb-web/src/assets/i18n/de.json | 5 +++- kdb-web/src/assets/i18n/en.json | 5 +++- 9 files changed, 45 insertions(+), 26 deletions(-) create mode 100644 kdb-bot/src/bot_graphql/queries/achievement_history_query.py diff --git a/kdb-bot/src/bot_data/migration/achievements_migration.py b/kdb-bot/src/bot_data/migration/achievements_migration.py index d9851cb5..eb6933ec 100644 --- a/kdb-bot/src/bot_data/migration/achievements_migration.py +++ b/kdb-bot/src/bot_data/migration/achievements_migration.py @@ -40,11 +40,11 @@ class AchievementsMigration(MigrationABC): CREATE TABLE IF NOT EXISTS `AchievementsHistory` ( `Id` BIGINT(20) NOT NULL, - `ServerId` BIGINT, `Name` VARCHAR(255) NOT NULL, `Attribute` VARCHAR(255) NOT NULL, `Operator` VARCHAR(255) NOT NULL, `Value` VARCHAR(255) NOT NULL, + `ServerId` BIGINT, `Deleted` BOOL DEFAULT FALSE, `DateFrom` DATETIME(6) NOT NULL, `DateTo` DATETIME(6) NOT NULL diff --git a/kdb-bot/src/bot_data/model/achievement_history.py b/kdb-bot/src/bot_data/model/achievement_history.py index 74208075..2fd5d218 100644 --- a/kdb-bot/src/bot_data/model/achievement_history.py +++ b/kdb-bot/src/bot_data/model/achievement_history.py @@ -1,20 +1,14 @@ -from datetime import datetime -from typing import Optional - -from cpl_core.database import TableABC - from bot_data.abc.history_table_abc import HistoryTableABC -from bot_data.model.server import Server -class Achievement(HistoryTableABC): +class AchievementHistory(HistoryTableABC): def __init__( self, name: str, attribute: str, operator: str, value: str, - server: Optional[Server], + server: int, deleted: bool, date_from: str, date_to: str, @@ -41,26 +35,18 @@ class Achievement(HistoryTableABC): def name(self) -> str: return self._name - @name.setter - def name(self, value: str): - self._name = value + @property + def attribute(self) -> str: + return self._attribute @property def operator(self) -> str: return self._operator - @operator.setter - def operator(self, value: str): - self._operator = value - @property def value(self) -> str: return self._value - @value.setter - def value(self, value: str): - self._value = value - @property - def server(self) -> Server: + def server(self) -> int: return self._server diff --git a/kdb-bot/src/bot_data/model/user_history.py b/kdb-bot/src/bot_data/model/user_history.py index d3b88ca7..2bf39954 100644 --- a/kdb-bot/src/bot_data/model/user_history.py +++ b/kdb-bot/src/bot_data/model/user_history.py @@ -9,6 +9,8 @@ class UserHistory(HistoryTableABC): self, dc_id: int, xp: int, + message_count: int, + reaction_count: int, server: int, deleted: bool, date_from: str, @@ -20,6 +22,8 @@ class UserHistory(HistoryTableABC): self._user_id = id self._discord_id = dc_id self._xp = xp + self._message_count = message_count + self._reaction_count = reaction_count self._server = server self._deleted = deleted @@ -38,6 +42,14 @@ class UserHistory(HistoryTableABC): def xp(self) -> int: return self._xp + @property + def message_count(self) -> int: + return self._message_count + + @property + def reaction_count(self) -> int: + return self._reaction_count + @property def server(self) -> int: return self._server diff --git a/kdb-bot/src/bot_graphql/graphql_module.py b/kdb-bot/src/bot_graphql/graphql_module.py index 5e54b86d..480b4abc 100644 --- a/kdb-bot/src/bot_graphql/graphql_module.py +++ b/kdb-bot/src/bot_graphql/graphql_module.py @@ -27,6 +27,7 @@ from bot_graphql.mutations.level_mutation import LevelMutation 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 +from bot_graphql.queries.achievement_history_query import AchievementHistoryQuery from bot_graphql.queries.achievement_query import AchievementQuery from bot_graphql.queries.auto_role_history_query import AutoRoleHistoryQuery from bot_graphql.queries.auto_role_query import AutoRoleQuery @@ -69,6 +70,7 @@ class GraphQLModule(ModuleABC): # queries services.add_transient(QueryABC, AchievementAttributeQuery) services.add_transient(QueryABC, AchievementQuery) + services.add_transient(QueryABC, AchievementHistoryQuery) services.add_transient(QueryABC, AutoRoleHistoryQuery) services.add_transient(QueryABC, AutoRoleQuery) services.add_transient(QueryABC, AutoRoleRuleHistoryQuery) diff --git a/kdb-bot/src/bot_graphql/model/achievement.gql b/kdb-bot/src/bot_graphql/model/achievement.gql index 7cd86cf9..a49cdae9 100644 --- a/kdb-bot/src/bot_graphql/model/achievement.gql +++ b/kdb-bot/src/bot_graphql/model/achievement.gql @@ -28,7 +28,7 @@ type AchievementHistory implements HistoryTableQuery { operator: String value: String - server: Server + server: ID deleted: Boolean dateFrom: String diff --git a/kdb-bot/src/bot_graphql/queries/achievement_history_query.py b/kdb-bot/src/bot_graphql/queries/achievement_history_query.py new file mode 100644 index 00000000..f8a8eddf --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/achievement_history_query.py @@ -0,0 +1,13 @@ +from bot_graphql.abc.history_query_abc import HistoryQueryABC + + +class AchievementHistoryQuery(HistoryQueryABC): + def __init__(self): + HistoryQueryABC.__init__(self, "Achievement") + + self.set_field("id", lambda x, *_: x.id) + self.set_field("name", lambda x, *_: x.name) + self.set_field("attribute", lambda x, *_: x.attribute) + self.set_field("operator", lambda x, *_: x.operator) + self.set_field("value", lambda x, *_: x.value) + self.set_field("server", lambda x, *_: x.server) diff --git a/kdb-bot/src/bot_graphql/queries/achievement_query.py b/kdb-bot/src/bot_graphql/queries/achievement_query.py index 46ee137d..e64ff3db 100644 --- a/kdb-bot/src/bot_graphql/queries/achievement_query.py +++ b/kdb-bot/src/bot_graphql/queries/achievement_query.py @@ -1,6 +1,6 @@ from cpl_core.database.context import DatabaseContextABC -from bot_data.model.user_history import UserHistory +from bot_data.model.achievement_history import AchievementHistory from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC @@ -9,7 +9,7 @@ class AchievementQuery(DataQueryWithHistoryABC): self, db: DatabaseContextABC, ): - DataQueryWithHistoryABC.__init__(self, "Achievement", "AchievementsHistory", UserHistory, db) + DataQueryWithHistoryABC.__init__(self, "Achievement", "AchievementsHistory", AchievementHistory, db) self.set_field("id", lambda x, *_: x.id) self.set_field("name", lambda x, *_: x.name) diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index 6bcc1328..e8d1bde5 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -147,7 +147,10 @@ "permissions": "Berechtigung", "roleId": "Rolle", "server": "Server", - "xp": "XP" + "xp": "XP", + "attribute": "Attribut", + "operator": "Operator", + "value": "Wert" }, "id": "Id", "joined_at": "Beigetreten am", diff --git a/kdb-web/src/assets/i18n/en.json b/kdb-web/src/assets/i18n/en.json index 862fcf4a..b4e584ad 100644 --- a/kdb-web/src/assets/i18n/en.json +++ b/kdb-web/src/assets/i18n/en.json @@ -147,7 +147,10 @@ "permissions": "Permissions", "roleId": "Role", "server": "Server", - "xp": "XP" + "xp": "XP", + "attribute": "Attribute", + "operator": "Operator", + "value": "Value" }, "id": "Id", "joined_at": "Joined at", -- 2.45.2 From 23d621602922d1b41096aaabdec62622cb41fa74 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 16 Jul 2023 13:30:57 +0200 Subject: [PATCH 033/127] Added description to achievements #268_achievements --- .../abc/achievement_repository_abc.py | 4 +++ .../migration/achievements_migration.py | 28 +++++++++++-------- kdb-bot/src/bot_data/model/achievement.py | 14 +++++++++- .../src/bot_data/model/achievement_history.py | 6 ++++ .../bot_data/model/user_got_achievement.py | 9 ++++++ .../achievements_repository_service.py | 17 +++++++++-- .../bot_graphql/filter/achievement_filter.py | 11 ++++++-- kdb-bot/src/bot_graphql/model/achievement.gql | 4 +++ .../mutations/achievement_mutation.py | 7 +++++ .../queries/achievement_history_query.py | 1 + .../bot_graphql/queries/achievement_query.py | 1 + .../src/app/models/data/achievement.model.ts | 2 ++ .../src/app/models/graphql/mutations.model.ts | 10 ++++--- .../src/app/models/graphql/queries.model.ts | 2 ++ .../achievement/achievement.component.html | 24 ++++++++++++++++ .../achievement/achievement.component.ts | 2 ++ kdb-web/src/assets/i18n/de.json | 1 + 17 files changed, 123 insertions(+), 20 deletions(-) diff --git a/kdb-bot/src/bot_data/abc/achievement_repository_abc.py b/kdb-bot/src/bot_data/abc/achievement_repository_abc.py index 3850dc27..ff3014fe 100644 --- a/kdb-bot/src/bot_data/abc/achievement_repository_abc.py +++ b/kdb-bot/src/bot_data/abc/achievement_repository_abc.py @@ -27,6 +27,10 @@ class AchievementRepositoryABC(ABC): def get_achievements_by_user_id(self, user_id: int) -> List[Achievement]: pass + @abstractmethod + def get_user_got_achievements_by_achievement_id(self, achievement_id: int) -> List[Achievement]: + pass + @abstractmethod def add_achievement(self, achievement: Achievement): pass diff --git a/kdb-bot/src/bot_data/migration/achievements_migration.py b/kdb-bot/src/bot_data/migration/achievements_migration.py index eb6933ec..f3a454d3 100644 --- a/kdb-bot/src/bot_data/migration/achievements_migration.py +++ b/kdb-bot/src/bot_data/migration/achievements_migration.py @@ -21,6 +21,7 @@ class AchievementsMigration(MigrationABC): CREATE TABLE IF NOT EXISTS `Achievements` ( `Id` BIGINT NOT NULL AUTO_INCREMENT, `Name` VARCHAR(255) NOT NULL, + `Description` VARCHAR(255) NOT NULL, `Attribute` VARCHAR(255) NOT NULL, `Operator` VARCHAR(255) NOT NULL, `Value` VARCHAR(255) NOT NULL, @@ -41,6 +42,7 @@ class AchievementsMigration(MigrationABC): ( `Id` BIGINT(20) NOT NULL, `Name` VARCHAR(255) NOT NULL, + `Description` VARCHAR(255) NOT NULL, `Attribute` VARCHAR(255) NOT NULL, `Operator` VARCHAR(255) NOT NULL, `Value` VARCHAR(255) NOT NULL, @@ -77,41 +79,45 @@ class AchievementsMigration(MigrationABC): self._cursor.execute(str(f"""ALTER TABLE UsersHistory ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP;""")) self._cursor.execute(str(f"""ALTER TABLE UsersHistory ADD ReactionCount BIGINT NOT NULL DEFAULT 0 AFTER XP;""")) + self._cursor.execute(str(f"""DROP TRIGGER IF EXISTS `TR_AchievementsUpdate`;""")) self._cursor.execute( str( f""" - DROP TRIGGER IF EXISTS `TR_AchievementsUpdate`; - CREATE TRIGGER `TR_AchievementsUpdate` AFTER UPDATE ON `Achievements` FOR EACH ROW BEGIN INSERT INTO `AchievementsHistory` ( - `Id`, `Name`, `Attribute`, `Operator`, `Value`, `ServerId`, `DateFrom`, `DateTo` + `Id`, `Name`, `Description`, `Attribute`, `Operator`, `Value`, `ServerId`, `DateFrom`, `DateTo` ) VALUES ( - OLD.Id, OLD.Name, OLD.Attribute, OLD.Operator, OLD.Value, OLD.ServerId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + OLD.Id, OLD.Name, OLD.Description, OLD.Attribute, OLD.Operator, OLD.Value, OLD.ServerId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) ); END; - - DROP TRIGGER IF EXISTS `TR_AchievementsDelete`; - + """ + ) + ) + + self._cursor.execute(str(f"""DROP TRIGGER IF EXISTS `TR_AchievementsDelete`;""")) + + self._cursor.execute( + str( + f""" CREATE TRIGGER `TR_AchievementsDelete` AFTER DELETE ON `Achievements` FOR EACH ROW BEGIN INSERT INTO `AchievementsHistory` ( - `Id`, `Name`, `Attribute`, `Operator`, `Value`, `ServerId`, `Deleted`, `DateFrom`, `DateTo` + `Id`, `Name`, `Description`, `Attribute`, `Operator`, `Value`, `ServerId`, `Deleted`, `DateFrom`, `DateTo` ) VALUES ( - OLD.Id, OLD.Name, OLD.Attribute, OLD.Operator, OLD.Value, OLD.ServerId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + OLD.Id, OLD.Name, OLD.Description, OLD.Attribute, OLD.Operator, OLD.Value, OLD.ServerId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) ); END; """ - ), - multi=True, + ) ) def downgrade(self): diff --git a/kdb-bot/src/bot_data/model/achievement.py b/kdb-bot/src/bot_data/model/achievement.py index 9766710e..0b33b693 100644 --- a/kdb-bot/src/bot_data/model/achievement.py +++ b/kdb-bot/src/bot_data/model/achievement.py @@ -11,6 +11,7 @@ class Achievement(TableABC): def __init__( self, name: str, + description: str, attribute: str, operator: str, value: str, @@ -21,6 +22,7 @@ class Achievement(TableABC): ): self._id = id self._name = name + self._description = description self._attribute = attribute if self._is_operator_valid(operator): @@ -53,6 +55,14 @@ class Achievement(TableABC): def name(self, value: str): self._name = value + @property + def description(self) -> str: + return self._description + + @description.setter + def description(self, value: str): + self._description = value + @property def attribute(self) -> str: return self._attribute @@ -103,9 +113,10 @@ class Achievement(TableABC): return str( f""" INSERT INTO `Achievements` ( - `Name`, `Attribute`, `Operator`, `Value`, `ServerId` + `Name`, `Description`, `Attribute`, `Operator`, `Value`, `ServerId` ) VALUES ( '{self._name}', + '{self._description}', '{self._attribute}', '{self._operator}', '{self._value}', @@ -120,6 +131,7 @@ class Achievement(TableABC): f""" UPDATE `Achievements` SET `Name` = '{self._name}', + `Description` = '{self._description}', `Attribute` = '{self._attribute}', `Operator` = '{self._operator}', `Value` = '{self._value}' diff --git a/kdb-bot/src/bot_data/model/achievement_history.py b/kdb-bot/src/bot_data/model/achievement_history.py index 2fd5d218..ae8a9230 100644 --- a/kdb-bot/src/bot_data/model/achievement_history.py +++ b/kdb-bot/src/bot_data/model/achievement_history.py @@ -5,6 +5,7 @@ class AchievementHistory(HistoryTableABC): def __init__( self, name: str, + description: str, attribute: str, operator: str, value: str, @@ -18,6 +19,7 @@ class AchievementHistory(HistoryTableABC): self._id = id self._name = name + self._description = description self._attribute = attribute self._operator = operator self._value = value @@ -35,6 +37,10 @@ class AchievementHistory(HistoryTableABC): def name(self) -> str: return self._name + @property + def description(self) -> str: + return self._description + @property def attribute(self) -> str: return self._attribute diff --git a/kdb-bot/src/bot_data/model/user_got_achievement.py b/kdb-bot/src/bot_data/model/user_got_achievement.py index 18bb6b92..d2c37cf5 100644 --- a/kdb-bot/src/bot_data/model/user_got_achievement.py +++ b/kdb-bot/src/bot_data/model/user_got_achievement.py @@ -62,6 +62,15 @@ class UserGotAchievement(TableABC): """ ) + @staticmethod + def get_select_by_achievement_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `UserGotAchievements` + WHERE `AchievementId` = {id}; + """ + ) + @property def insert_string(self) -> str: return str( diff --git a/kdb-bot/src/bot_data/service/achievements_repository_service.py b/kdb-bot/src/bot_data/service/achievements_repository_service.py index 130da9c8..9c7e9117 100644 --- a/kdb-bot/src/bot_data/service/achievements_repository_service.py +++ b/kdb-bot/src/bot_data/service/achievements_repository_service.py @@ -31,9 +31,10 @@ class AchievementRepositoryService(AchievementRepositoryABC): result[2], result[3], result[4], - self._servers.get_server_by_id(result[5]), - result[6], + result[5], + self._servers.get_server_by_id(result[6]), result[7], + result[8], id=result[0], ) @@ -89,6 +90,18 @@ class AchievementRepositoryService(AchievementRepositoryABC): return achievements + def get_user_got_achievements_by_achievement_id(self, achievement_id: int) -> List[Achievement]: + achievements_joins = List(UserGotAchievement) + self._logger.trace( + __name__, f"Send SQL command: {UserGotAchievement.get_select_by_achievement_id_string(achievement_id)}" + ) + results = self._context.select(UserGotAchievement.get_select_by_achievement_id_string(achievement_id)) + for result in results: + self._logger.trace(__name__, f"Got UserGotAchievement with id {result[0]}") + achievements_joins.append(self._join_from_result(result)) + + return achievements_joins + def add_achievement(self, achievement: Achievement): self._logger.trace(__name__, f"Send SQL command: {achievement.insert_string}") self._context.cursor.execute(achievement.insert_string) diff --git a/kdb-bot/src/bot_graphql/filter/achievement_filter.py b/kdb-bot/src/bot_graphql/filter/achievement_filter.py index 49c0eab9..674af502 100644 --- a/kdb-bot/src/bot_graphql/filter/achievement_filter.py +++ b/kdb-bot/src/bot_graphql/filter/achievement_filter.py @@ -10,6 +10,7 @@ class AchievementFilter(FilterABC): self._id = None self._name = None + self._description = None self._attribute = None self._operator = None self._value = None @@ -22,6 +23,9 @@ class AchievementFilter(FilterABC): if "name" in values: self._name = values["name"] + if "description" in values: + self._description = values["description"] + if "attribute" in values: self._attribute = values["attribute"] @@ -42,10 +46,13 @@ class AchievementFilter(FilterABC): query = query.where(lambda x: x.id == self._id) if self._name is not None: - query = query.where(lambda x: x.name == self._name) + query = query.where(lambda x: x.name == self._name or self._name in x.name) + + if self._description is not None: + query = query.where(lambda x: x.description == self._description or self._description in x.description) if self._attribute is not None: - query = query.where(lambda x: x.attribute == self._attribute) + query = query.where(lambda x: x.attribute == self._attribute or self._attribute in x.attribute) if self._operator is not None: query = query.where(lambda x: x.operator == self._operator) diff --git a/kdb-bot/src/bot_graphql/model/achievement.gql b/kdb-bot/src/bot_graphql/model/achievement.gql index a49cdae9..df16dd4e 100644 --- a/kdb-bot/src/bot_graphql/model/achievement.gql +++ b/kdb-bot/src/bot_graphql/model/achievement.gql @@ -9,6 +9,7 @@ type AchievementAttribute { type Achievement implements TableWithHistoryQuery { id: ID name: String + description: String attribute: String operator: String value: String @@ -24,6 +25,7 @@ type Achievement implements TableWithHistoryQuery { type AchievementHistory implements HistoryTableQuery { id: ID name: String + description: String attribute: String operator: String value: String @@ -38,6 +40,7 @@ type AchievementHistory implements HistoryTableQuery { input AchievementFilter { id: ID name: String + description: String attribute: String operator: String value: String @@ -53,6 +56,7 @@ type AchievementMutation { input AchievementInput { id: ID name: String + description: String attribute: String operator: String value: String diff --git a/kdb-bot/src/bot_graphql/mutations/achievement_mutation.py b/kdb-bot/src/bot_graphql/mutations/achievement_mutation.py index 99459515..40975a38 100644 --- a/kdb-bot/src/bot_graphql/mutations/achievement_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/achievement_mutation.py @@ -36,6 +36,7 @@ class AchievementMutation(QueryABC): achievement = Achievement( input["name"], + input["description"], input["attribute"], input["operator"], input["value"], @@ -47,6 +48,7 @@ class AchievementMutation(QueryABC): def get_new_achievement(a: Achievement): return ( a.name == achievement.name + and a.description == achievement.description and a.attribute == achievement.attribute and a.operator == achievement.operator and a.value == achievement.value @@ -60,6 +62,7 @@ class AchievementMutation(QueryABC): self._can_user_mutate_data(achievement.server, UserRoleEnum.moderator) achievement.name = input["name"] if "name" in input else achievement.name + achievement.description = input["description"] if "description" in input else achievement.description achievement.attribute = input["attribute"] if "attribute" in input else achievement.attribute achievement.operator = input["operator"] if "operator" in input else achievement.operator achievement.value = input["value"] if "value" in input else achievement.value @@ -74,6 +77,10 @@ class AchievementMutation(QueryABC): achievement = self._achievements.get_achievement_by_id(id) self._can_user_mutate_data(achievement.server, UserRoleEnum.admin) + joins = self._achievements.get_user_got_achievements_by_achievement_id(id) + for join in joins: + self._achievements.delete_user_got_achievement(join) + self._achievements.delete_achievement(achievement) self._db.save_changes() diff --git a/kdb-bot/src/bot_graphql/queries/achievement_history_query.py b/kdb-bot/src/bot_graphql/queries/achievement_history_query.py index f8a8eddf..d8db3fd3 100644 --- a/kdb-bot/src/bot_graphql/queries/achievement_history_query.py +++ b/kdb-bot/src/bot_graphql/queries/achievement_history_query.py @@ -7,6 +7,7 @@ class AchievementHistoryQuery(HistoryQueryABC): self.set_field("id", lambda x, *_: x.id) self.set_field("name", lambda x, *_: x.name) + self.set_field("description", lambda x, *_: x.description) self.set_field("attribute", lambda x, *_: x.attribute) self.set_field("operator", lambda x, *_: x.operator) self.set_field("value", lambda x, *_: x.value) diff --git a/kdb-bot/src/bot_graphql/queries/achievement_query.py b/kdb-bot/src/bot_graphql/queries/achievement_query.py index e64ff3db..ab72fde0 100644 --- a/kdb-bot/src/bot_graphql/queries/achievement_query.py +++ b/kdb-bot/src/bot_graphql/queries/achievement_query.py @@ -13,6 +13,7 @@ class AchievementQuery(DataQueryWithHistoryABC): self.set_field("id", lambda x, *_: x.id) self.set_field("name", lambda x, *_: x.name) + self.set_field("description", lambda x, *_: x.description) self.set_field("attribute", lambda x, *_: x.attribute) self.set_field("operator", lambda x, *_: x.operator) self.set_field("value", lambda x, *_: x.value) diff --git a/kdb-web/src/app/models/data/achievement.model.ts b/kdb-web/src/app/models/data/achievement.model.ts index 84f6f88e..c32b6440 100644 --- a/kdb-web/src/app/models/data/achievement.model.ts +++ b/kdb-web/src/app/models/data/achievement.model.ts @@ -9,6 +9,7 @@ export interface AchievementAttribute { export interface Achievement extends DataWithHistory { id?: number; name?: string; + description?: string; attribute?: string | AchievementAttribute; operator?: string; value?: string; @@ -20,6 +21,7 @@ export interface Achievement extends DataWithHistory { export interface AchievementFilter { id?: number; name?: string; + description?: string; attribute?: string; operator?: string; value?: string; diff --git a/kdb-web/src/app/models/graphql/mutations.model.ts b/kdb-web/src/app/models/graphql/mutations.model.ts index df3b539d..ac4448d0 100644 --- a/kdb-web/src/app/models/graphql/mutations.model.ts +++ b/kdb-web/src/app/models/graphql/mutations.model.ts @@ -123,11 +123,12 @@ export class Mutations { `; static createAchievement = ` - mutation createAchievement($name: String, $attribute: String, $operator: String, $value: String, $serverId: ID) { + mutation createAchievement($name: String, $description: String, $attribute: String, $operator: String, $value: String, $serverId: ID) { achievement { - createAchievement(input: { name: $name, attribute: $attribute, operator: $operator, value: $value, serverId: $serverId}) { + createAchievement(input: { name: $name, description: $description, attribute: $attribute, operator: $operator, value: $value, serverId: $serverId}) { id name + description attribute operator value @@ -140,11 +141,12 @@ export class Mutations { `; static updateAchievement = ` - mutation updateAchievement($id: ID, $name: String, $attribute: String, $operator: String, $value: String) { + mutation updateAchievement($id: ID, $name: String, $description: String, $attribute: String, $operator: String, $value: String) { achievement { - updateAchievement(input: { id: $id, name: $name, attribute: $attribute, operator: $operator, value: $value}) { + updateAchievement(input: { id: $id, name: $name, description: $description, attribute: $attribute, operator: $operator, value: $value}) { id name + description attribute operator value diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts index 453b7b64..6dc78904 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -117,6 +117,7 @@ export class Queries { achievements(filter: $filter, page: $page, sort: $sort) { id name + description attribute operator value @@ -141,6 +142,7 @@ export class Queries { history { id name + description attribute operator value diff --git a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html index e9ceeb2a..44f88ad5 100644 --- a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html +++ b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html @@ -43,6 +43,13 @@
+ +
+
{{'view.server.achievements.headers.description' | translate}}
+ +
+ +
{{'view.server.achievements.headers.attribute' | translate}}
@@ -96,6 +103,12 @@ placeholder="{{'view.server.achievements.headers.name' | translate}}"> + +
+ +
+ @@ -129,6 +142,17 @@ + + + + + + + {{achievement.description}} + + + + 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 13d18fe7..114d1d8a 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 @@ -227,6 +227,7 @@ export class AchievementComponent implements OnInit, OnDestroy { this.spinner.showSpinner(); this.data.mutation(Mutations.createAchievement, { name: newAchievement.name, + description: newAchievement.description, attribute: newAchievement.attribute, operator: newAchievement.operator, value: newAchievement.value + "", @@ -250,6 +251,7 @@ export class AchievementComponent implements OnInit, OnDestroy { this.data.mutation(Mutations.updateAchievement, { id: newAchievement.id, name: newAchievement.name, + description: newAchievement.description, attribute: newAchievement.attribute, operator: newAchievement.operator, value: newAchievement.value + "" diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index e8d1bde5..7deee1ea 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -326,6 +326,7 @@ "headers": { "attribute": "Attribut", "name": "Name", + "description": "Beschreibung", "operator": "Operator", "value": "Wert" }, -- 2.45.2 From d4dd55944a0b0086e8fd706fa015a2fff718f8bb Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 17 Jul 2023 11:09:34 +0200 Subject: [PATCH 034/127] Add xp for achievement #268_achievements --- kdb-bot/src/bot/config | 2 +- .../src/modules/achievements/achievement_service.py | 11 +++++++++++ .../base/configuration/base_server_settings.py | 5 +++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/kdb-bot/src/bot/config b/kdb-bot/src/bot/config index 0179ab1e..440fb3bd 160000 --- a/kdb-bot/src/bot/config +++ b/kdb-bot/src/bot/config @@ -1 +1 @@ -Subproject commit 0179ab1ed725c233c5844ee94ed51cad176d9c7e +Subproject commit 440fb3bd353dce31a2408c977a3168e3cfc32f9a diff --git a/kdb-bot/src/modules/achievements/achievement_service.py b/kdb-bot/src/modules/achievements/achievement_service.py index b446d095..9e8a0ed8 100644 --- a/kdb-bot/src/modules/achievements/achievement_service.py +++ b/kdb-bot/src/modules/achievements/achievement_service.py @@ -8,11 +8,13 @@ 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.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: @@ -22,6 +24,7 @@ class AchievementService: logger: LoggerABC, bot: DiscordBotServiceABC, achievements: AchievementRepositoryABC, + users: UserRepositoryABC, db: DatabaseContextABC, message_service: MessageService, resolver: AchievementAttributeResolver, @@ -31,6 +34,7 @@ class AchievementService: self._logger = logger self._bot = bot self._achievements = achievements + self._users = users self._db = db self._message_service = message_service self._t = t @@ -92,8 +96,15 @@ class AchievementService: self._achievements.add_user_got_achievement(UserGotAchievement(user, achievement, user.server)) self._db.save_changes() + await self._give_user_xp(user) await self._send_achievement_notification(user.server.discord_id, user.discord_id, achievement.name) + async def _give_user_xp(self, user: User): + settings: BaseServerSettings = self._config.get_configuration(f"BaseServerSettings_{user.server.discord_id}") + user.xp += settings.xp_per_achievement + self._users.update_user(user) + self._db.save_changes() + 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) diff --git a/kdb-bot/src/modules/base/configuration/base_server_settings.py b/kdb-bot/src/modules/base/configuration/base_server_settings.py index f0538374..8bd987b4 100644 --- a/kdb-bot/src/modules/base/configuration/base_server_settings.py +++ b/kdb-bot/src/modules/base/configuration/base_server_settings.py @@ -16,6 +16,7 @@ class BaseServerSettings(ConfigurationModelABC): 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 = "" @@ -51,6 +52,10 @@ class BaseServerSettings(ConfigurationModelABC): 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 -- 2.45.2 From 11a4874bfb16d83e24366b0971dbb76c27cf022e Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 18 Jul 2023 11:10:02 +0200 Subject: [PATCH 035/127] Added achievements to data integrity service #268_achievements --- .../service/data_integrity_service.py | 23 +++++++++++++++++++ .../achievements/achievement_service.py | 6 ++--- 2 files changed, 26 insertions(+), 3 deletions(-) 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 c3f76912..01f55653 100644 --- a/kdb-bot/src/bot_core/service/data_integrity_service.py +++ b/kdb-bot/src/bot_core/service/data_integrity_service.py @@ -24,6 +24,7 @@ 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 @@ -42,6 +43,7 @@ class DataIntegrityService: user_joins: UserJoinedServerRepositoryABC, user_joins_vc: UserJoinedVoiceChannelRepositoryABC, user_joined_gs: UserJoinedGameServerRepositoryABC, + achievement_service: AchievementService, dtp: DateTimeOffsetPipe, ): self._config = config @@ -57,6 +59,7 @@ class DataIntegrityService: self._user_joins = user_joins self._user_joins_vc = user_joins_vc self._user_joined_gs = user_joined_gs + self._achievements = achievement_service self._dtp = dtp self._is_for_shutdown = False @@ -360,6 +363,25 @@ class DataIntegrityService: except Exception as e: self._logger.error(__name__, f"Cannot get UserJoinedGameServer", e) + def _check_for_user_achievements(self): + self._logger.debug(__name__, f"Start checking UserGotAchievement table") + + for guild in self._bot.guilds: + server = self._servers.find_server_by_discord_id(guild.id) + if server is None: + self._logger.fatal(__name__, f"Server not found in database: {guild.id}") + + for member in guild.members: + if member.bot: + self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot") + continue + + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) + if user is None: + self._logger.fatal(__name__, f"User not found in database: {member.id}") + + self._bot.loop.create_task(self._achievements.validate_achievements_for_user(user)) + def check_data_integrity(self, is_for_shutdown=False): if is_for_shutdown != self._is_for_shutdown: self._is_for_shutdown = is_for_shutdown @@ -371,3 +393,4 @@ class DataIntegrityService: self._check_user_joins() self._check_user_joins_vc() self._check_user_joined_gs() + self._check_for_user_achievements() diff --git a/kdb-bot/src/modules/achievements/achievement_service.py b/kdb-bot/src/modules/achievements/achievement_service.py index 9e8a0ed8..fe875965 100644 --- a/kdb-bot/src/modules/achievements/achievement_service.py +++ b/kdb-bot/src/modules/achievements/achievement_service.py @@ -78,7 +78,7 @@ class AchievementService: return self._attributes def _match(self, value: any, operator: str, expected_value: str) -> bool: - return self._operators[operator](value, expected_value) + return self._operators[operator](str(value), expected_value) def has_user_achievement_already(self, user: User, achievement: Achievement) -> bool: user_achievements = self._achievements.get_achievements_by_user_id(user.id) @@ -96,10 +96,10 @@ class AchievementService: self._achievements.add_user_got_achievement(UserGotAchievement(user, achievement, user.server)) self._db.save_changes() - await self._give_user_xp(user) + self._give_user_xp(user) await self._send_achievement_notification(user.server.discord_id, user.discord_id, achievement.name) - async def _give_user_xp(self, user: User): + def _give_user_xp(self, user: User): settings: BaseServerSettings = self._config.get_configuration(f"BaseServerSettings_{user.server.discord_id}") user.xp += settings.xp_per_achievement self._users.update_user(user) -- 2.45.2 From 9f63a9c6dd82583bfac115fa275086f5a5dc55fc Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 17 Jul 2023 13:43:27 +0200 Subject: [PATCH 036/127] [UNTESTED] Added complaint command #293_complaints --- kdb-bot/src/bot/translation/de.json | 5 +++ kdb-bot/src/modules/base/base_module.py | 6 +++ .../modules/base/command/complaint_command.py | 25 +++++++++++ kdb-bot/src/modules/base/forms/__init__.py | 1 + .../src/modules/base/forms/complaint_form.py | 44 +++++++++++++++++++ 5 files changed, 81 insertions(+) create mode 100644 kdb-bot/src/modules/base/command/complaint_command.py create mode 100644 kdb-bot/src/modules/base/forms/__init__.py create mode 100644 kdb-bot/src/modules/base/forms/complaint_form.py diff --git a/kdb-bot/src/bot/translation/de.json b/kdb-bot/src/bot/translation/de.json index 27dd9749..d231e3f4 100644 --- a/kdb-bot/src/bot/translation/de.json +++ b/kdb-bot/src/bot/translation/de.json @@ -151,6 +151,11 @@ } }, "base": { + "complaints": { + "title": "Beschwerde einreichen", + "label": "Beschwerde", + "message": "{} hat eine Beschwerde eingereicht:\n{}" + }, "afk_command_channel_missing_message": "Zu unfähig einem Sprachkanal beizutreten?", "afk_command_move_message": "Ich verschiebe dich ja schon... (◔_◔)", "game_server": { diff --git a/kdb-bot/src/modules/base/base_module.py b/kdb-bot/src/modules/base/base_module.py index 4d8c4f2d..95604372 100644 --- a/kdb-bot/src/modules/base/base_module.py +++ b/kdb-bot/src/modules/base/base_module.py @@ -8,6 +8,7 @@ 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.complaint_command import ComplaintCommand from modules.base.command.game_server_group import GameServerGroup from modules.base.command.help_command import HelpCommand from modules.base.command.info_command import InfoCommand @@ -36,6 +37,7 @@ from modules.base.events.base_on_voice_state_update_event_help_channel import ( from modules.base.events.base_on_voice_state_update_event_scheduled_event_bonus import ( BaseOnVoiceStateUpdateEventScheduledEventBonus, ) +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 @@ -55,8 +57,12 @@ class BaseModule(ModuleABC): services.add_singleton(EventService) services.add_transient(UserWarningsService) + # forms + services.add_singleton(ComplaintForm) + # commands self._dc.add_command(AFKCommand) + self._dc.add_command(ComplaintCommand) self._dc.add_command(HelpCommand) self._dc.add_command(InfoCommand) self._dc.add_command(MassMoveCommand) diff --git a/kdb-bot/src/modules/base/command/complaint_command.py b/kdb-bot/src/modules/base/command/complaint_command.py new file mode 100644 index 00000000..68b2b1e2 --- /dev/null +++ b/kdb-bot/src/modules/base/command/complaint_command.py @@ -0,0 +1,25 @@ +from cpl_core.logging import LoggerABC +from cpl_discord.command import DiscordCommandABC +from cpl_discord.service import DiscordBotServiceABC +from discord.ext import commands +from discord.ext.commands import Context + +from bot_core.helper.command_checks import CommandChecks +from modules.base.forms.complaint_form import ComplaintForm + + +class ComplaintCommand(DiscordCommandABC): + def __init__(self, logger: LoggerABC, bot: DiscordBotServiceABC, form: ComplaintForm): + DiscordCommandABC.__init__(self) + + self._logger = logger + self._bot = bot + self._form = form + + @commands.hybrid_command() + @commands.guild_only() + @CommandChecks.check_is_ready() + async def complaint(self, ctx: Context): + self._logger.debug(__name__, f"Received command complaint {ctx}") + await ctx.interaction.response.send_modal(self._form) + self._logger.trace(__name__, f"Finished command complaint {ctx}") diff --git a/kdb-bot/src/modules/base/forms/__init__.py b/kdb-bot/src/modules/base/forms/__init__.py new file mode 100644 index 00000000..425ab6c1 --- /dev/null +++ b/kdb-bot/src/modules/base/forms/__init__.py @@ -0,0 +1 @@ +# imports diff --git a/kdb-bot/src/modules/base/forms/complaint_form.py b/kdb-bot/src/modules/base/forms/complaint_form.py new file mode 100644 index 00000000..856b417d --- /dev/null +++ b/kdb-bot/src/modules/base/forms/complaint_form.py @@ -0,0 +1,44 @@ +import discord +from cpl_core.database.context import DatabaseContextABC +from cpl_translation import TranslatePipe +from discord import ui + +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 + + +class ComplaintForm(ui.Modal): + description = ui.TextInput(label="Complain about something", required=True) + + def __init__( + self, + db: DatabaseContextABC, + logger: CommandLogger, + message_service: MessageServiceABC, + base_helper: BaseHelperService, + t: TranslatePipe, + ): + ui.Modal.__init__(self, title=t.transform("modules.base.complaints.title")) + + 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.message.guild.id) + channel = interaction.guild.get_channel(settings.team_channel_id) + await self._message_service.send_channel_message( + channel, + self._t.transform("modules.base.complaints.message").format( + interaction.user.mention, self.description.value + ), + is_persistent=True, + ) + self._logger.trace(__name__, f"Finished complaint command form") -- 2.45.2 From d6423229858c3b189777f3d6a6d79a4c91b3ff1c Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 18 Jul 2023 11:30:05 +0200 Subject: [PATCH 037/127] Improved complaint command #293_complaints --- kdb-bot/src/bot/translation/de.json | 3 ++- kdb-bot/src/modules/base/forms/complaint_form.py | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/kdb-bot/src/bot/translation/de.json b/kdb-bot/src/bot/translation/de.json index d231e3f4..61f143e5 100644 --- a/kdb-bot/src/bot/translation/de.json +++ b/kdb-bot/src/bot/translation/de.json @@ -154,7 +154,8 @@ "complaints": { "title": "Beschwerde einreichen", "label": "Beschwerde", - "message": "{} hat eine Beschwerde eingereicht:\n{}" + "message": "{} hat eine Beschwerde eingereicht:\n{}", + "response": "Danke für deine Beschwerde" }, "afk_command_channel_missing_message": "Zu unfähig einem Sprachkanal beizutreten?", "afk_command_move_message": "Ich verschiebe dich ja schon... (◔_◔)", diff --git a/kdb-bot/src/modules/base/forms/complaint_form.py b/kdb-bot/src/modules/base/forms/complaint_form.py index 856b417d..6ae3b96e 100644 --- a/kdb-bot/src/modules/base/forms/complaint_form.py +++ b/kdb-bot/src/modules/base/forms/complaint_form.py @@ -1,7 +1,7 @@ import discord from cpl_core.database.context import DatabaseContextABC from cpl_translation import TranslatePipe -from discord import ui +from discord import ui, TextStyle from bot_core.abc.message_service_abc import MessageServiceABC from bot_core.logging.command_logger import CommandLogger @@ -10,7 +10,7 @@ from modules.base.service.base_helper_service import BaseHelperService class ComplaintForm(ui.Modal): - description = ui.TextInput(label="Complain about something", required=True) + description = ui.TextInput(label="Complain about something", required=True, style=TextStyle.long) def __init__( self, @@ -32,7 +32,7 @@ class ComplaintForm(ui.Modal): 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.message.guild.id) + settings: BaseServerSettings = self._base_helper.get_config(interaction.guild.id) channel = interaction.guild.get_channel(settings.team_channel_id) await self._message_service.send_channel_message( channel, @@ -41,4 +41,7 @@ class ComplaintForm(ui.Modal): ), is_persistent=True, ) + await self._message_service.send_interaction_msg( + interaction, self._t.transform("modules.base.complaints.response") + ) self._logger.trace(__name__, f"Finished complaint command form") -- 2.45.2 From 0a3affc5d072012c86bb5fadfef3fb98953ec8ac Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 18 Jul 2023 11:43:50 +0200 Subject: [PATCH 038/127] Added bug report #293_complaints --- kdb-bot/src/bot/translation/de.json | 6 +++ kdb-bot/src/modules/base/base_module.py | 6 ++- .../modules/base/command/complaint_command.py | 25 ---------- .../src/modules/base/command/submit_group.py | 43 ++++++++++++++++ .../src/modules/base/forms/bug_report_form.py | 50 +++++++++++++++++++ 5 files changed, 103 insertions(+), 27 deletions(-) delete mode 100644 kdb-bot/src/modules/base/command/complaint_command.py create mode 100644 kdb-bot/src/modules/base/command/submit_group.py create mode 100644 kdb-bot/src/modules/base/forms/bug_report_form.py diff --git a/kdb-bot/src/bot/translation/de.json b/kdb-bot/src/bot/translation/de.json index 61f143e5..c4939ad7 100644 --- a/kdb-bot/src/bot/translation/de.json +++ b/kdb-bot/src/bot/translation/de.json @@ -157,6 +157,12 @@ "message": "{} hat eine Beschwerde eingereicht:\n{}", "response": "Danke für deine Beschwerde" }, + "bug": { + "title": "Bug melden", + "label": "Bug", + "message": "{} meldet einen Bug:\n{}", + "response": "Danke für dein Feedback :D" + }, "afk_command_channel_missing_message": "Zu unfähig einem Sprachkanal beizutreten?", "afk_command_move_message": "Ich verschiebe dich ja schon... (◔_◔)", "game_server": { diff --git a/kdb-bot/src/modules/base/base_module.py b/kdb-bot/src/modules/base/base_module.py index 95604372..aad5292d 100644 --- a/kdb-bot/src/modules/base/base_module.py +++ b/kdb-bot/src/modules/base/base_module.py @@ -8,7 +8,6 @@ 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.complaint_command import ComplaintCommand from modules.base.command.game_server_group import GameServerGroup from modules.base.command.help_command import HelpCommand from modules.base.command.info_command import InfoCommand @@ -17,6 +16,7 @@ from modules.base.command.ping_command import PingCommand from modules.base.command.presence_command import PresenceCommand from modules.base.command.purge_command import PurgeCommand from modules.base.command.register_group import RegisterGroup +from modules.base.command.submit_group import SubmitGroup from modules.base.command.unregister_group import UnregisterGroup from modules.base.command.user_group import UserGroup from modules.base.events.base_on_command_error_event import BaseOnCommandErrorEvent @@ -37,6 +37,7 @@ from modules.base.events.base_on_voice_state_update_event_help_channel import ( from modules.base.events.base_on_voice_state_update_event_scheduled_event_bonus import ( BaseOnVoiceStateUpdateEventScheduledEventBonus, ) +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 @@ -58,11 +59,12 @@ class BaseModule(ModuleABC): services.add_transient(UserWarningsService) # forms + services.add_singleton(BugReportForm) services.add_singleton(ComplaintForm) # commands self._dc.add_command(AFKCommand) - self._dc.add_command(ComplaintCommand) + self._dc.add_command(SubmitGroup) self._dc.add_command(HelpCommand) self._dc.add_command(InfoCommand) self._dc.add_command(MassMoveCommand) diff --git a/kdb-bot/src/modules/base/command/complaint_command.py b/kdb-bot/src/modules/base/command/complaint_command.py deleted file mode 100644 index 68b2b1e2..00000000 --- a/kdb-bot/src/modules/base/command/complaint_command.py +++ /dev/null @@ -1,25 +0,0 @@ -from cpl_core.logging import LoggerABC -from cpl_discord.command import DiscordCommandABC -from cpl_discord.service import DiscordBotServiceABC -from discord.ext import commands -from discord.ext.commands import Context - -from bot_core.helper.command_checks import CommandChecks -from modules.base.forms.complaint_form import ComplaintForm - - -class ComplaintCommand(DiscordCommandABC): - def __init__(self, logger: LoggerABC, bot: DiscordBotServiceABC, form: ComplaintForm): - DiscordCommandABC.__init__(self) - - self._logger = logger - self._bot = bot - self._form = form - - @commands.hybrid_command() - @commands.guild_only() - @CommandChecks.check_is_ready() - async def complaint(self, ctx: Context): - self._logger.debug(__name__, f"Received command complaint {ctx}") - await ctx.interaction.response.send_modal(self._form) - self._logger.trace(__name__, f"Finished command complaint {ctx}") diff --git a/kdb-bot/src/modules/base/command/submit_group.py b/kdb-bot/src/modules/base/command/submit_group.py new file mode 100644 index 00000000..56812e14 --- /dev/null +++ b/kdb-bot/src/modules/base/command/submit_group.py @@ -0,0 +1,43 @@ +from cpl_core.logging import LoggerABC +from cpl_discord.command import DiscordCommandABC +from cpl_discord.service import DiscordBotServiceABC +from discord.ext import commands +from discord.ext.commands import Context + +from bot_core.helper.command_checks import CommandChecks +from modules.base.forms.bug_report_form import BugReportForm +from modules.base.forms.complaint_form import ComplaintForm + + +class SubmitGroup(DiscordCommandABC): + def __init__( + self, logger: LoggerABC, bot: DiscordBotServiceABC, complaint_form: ComplaintForm, bug_form: BugReportForm + ): + DiscordCommandABC.__init__(self) + + self._logger = logger + self._bot = bot + self._complaint_form = complaint_form + self._bug_form = bug_form + + @commands.hybrid_group() + @commands.guild_only() + async def submit(self, ctx: Context): + pass + + @submit.command() + @commands.guild_only() + @CommandChecks.check_is_ready() + async def complaint(self, ctx: Context): + self._logger.debug(__name__, f"Received command complaint {ctx}") + await ctx.interaction.response.send_modal(self._complaint_form) + self._logger.trace(__name__, f"Finished command complaint {ctx}") + pass + + @submit.command() + @commands.guild_only() + @CommandChecks.check_is_ready() + async def bug_report(self, ctx: Context): + self._logger.debug(__name__, f"Received command complaint {ctx}") + await ctx.interaction.response.send_modal(self._bug_form) + self._logger.trace(__name__, f"Finished command complaint {ctx}") diff --git a/kdb-bot/src/modules/base/forms/bug_report_form.py b/kdb-bot/src/modules/base/forms/bug_report_form.py new file mode 100644 index 00000000..85d24bce --- /dev/null +++ b/kdb-bot/src/modules/base/forms/bug_report_form.py @@ -0,0 +1,50 @@ +import discord +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC +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 + + +class BugReportForm(ui.Modal): + description = ui.TextInput(label="Report a bug", required=True, style=TextStyle.long) + + def __init__( + self, + bot_settings: BotSettings, + 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._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") + + async def on_submit(self, interaction: discord.Interaction): + self._logger.debug(__name__, f"Started bug report form") + + for t in self._bot_settings.technicians: + 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), + member, + without_tracking=True, + ) + + await self._message_service.send_interaction_msg(interaction, self._t.transform("modules.base.bug.response")) + self._logger.trace(__name__, f"Finished bug report form") -- 2.45.2 From 22bdf13835df6b9954b4ff8163239cafe6667688 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 14 Aug 2023 09:35:46 +0200 Subject: [PATCH 039/127] Fixed workspace #268_achievements --- kdb-bot/cpl-workspace.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kdb-bot/cpl-workspace.json b/kdb-bot/cpl-workspace.json index df40bb8b..c11fb4ac 100644 --- a/kdb-bot/cpl-workspace.json +++ b/kdb-bot/cpl-workspace.json @@ -18,8 +18,7 @@ "checks": "tools/checks/checks.json", "get-version": "tools/get_version/get-version.json", "post-build": "tools/post_build/post-build.json", - "set-version": "tools/set_version/set-version.json", - "modules/achievements": "src/modules/achievements/modules/achievements.json" + "set-version": "tools/set_version/set-version.json" }, "Scripts": { "format": "black ./", -- 2.45.2 From a482c72a56bdf7f22d0a9a2a2fa4c17c0a1847d0 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 14 Aug 2023 19:01:10 +0200 Subject: [PATCH 040/127] Moved version settings to version.json #294 --- kdb-web/package.json | 2 +- kdb-web/src/app/models/config/app-settings.ts | 21 ++++++ kdb-web/src/app/models/config/appsettings.ts | 10 --- .../app/services/settings/settings.service.ts | 72 +++++++++++-------- kdb-web/src/assets/version.json | 7 ++ kdb-web/update-version.ts | 10 +-- 6 files changed, 75 insertions(+), 47 deletions(-) create mode 100644 kdb-web/src/app/models/config/app-settings.ts delete mode 100644 kdb-web/src/app/models/config/appsettings.ts create mode 100644 kdb-web/src/assets/version.json diff --git a/kdb-web/package.json b/kdb-web/package.json index 70c9306f..d6381d85 100644 --- a/kdb-web/package.json +++ b/kdb-web/package.json @@ -1,6 +1,6 @@ { "name": "kdb-web", - "version": "1.0.dev268_achievements", + "version": "1.0.dev294_frontend_version", "scripts": { "ng": "ng", "update-version": "ts-node-esm update-version.ts", diff --git a/kdb-web/src/app/models/config/app-settings.ts b/kdb-web/src/app/models/config/app-settings.ts new file mode 100644 index 00000000..7f45d9a1 --- /dev/null +++ b/kdb-web/src/app/models/config/app-settings.ts @@ -0,0 +1,21 @@ +import { SoftwareVersion } from "./software-version"; +import { Theme } from '../view/theme'; + +export interface AppAndVersionSettings { + ApiURL: string; + PrivacyURL: string; + ImprintURL: string; + Themes: Theme[]; + WebVersion: SoftwareVersion; +} + +export interface AppSettings { + ApiURL: string; + PrivacyURL: string; + ImprintURL: string; + Themes: Theme[]; +} + +export interface VersionSettings { + WebVersion: SoftwareVersion; +} diff --git a/kdb-web/src/app/models/config/appsettings.ts b/kdb-web/src/app/models/config/appsettings.ts deleted file mode 100644 index f3f5796b..00000000 --- a/kdb-web/src/app/models/config/appsettings.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { SoftwareVersion } from "./software-version"; -import { Theme } from '../view/theme'; - -export interface Appsettings { - ApiURL: string; - PrivacyURL: string; - ImprintURL: string; - WebVersion: SoftwareVersion; - Themes: Theme[]; -} diff --git a/kdb-web/src/app/services/settings/settings.service.ts b/kdb-web/src/app/services/settings/settings.service.ts index 81afc135..d1c3809f 100644 --- a/kdb-web/src/app/services/settings/settings.service.ts +++ b/kdb-web/src/app/services/settings/settings.service.ts @@ -1,76 +1,86 @@ import { HttpClient } from "@angular/common/http"; import { Injectable } from "@angular/core"; -import { throwError } from "rxjs"; +import { forkJoin, throwError } from "rxjs"; import { catchError } from "rxjs/operators"; -import { Appsettings } from "src/app/models/config/appsettings"; +import { AppAndVersionSettings, AppSettings, VersionSettings } from "src/app/models/config/app-settings"; import { SoftwareVersion } from "src/app/models/config/software-version"; import { Theme } from "src/app/models/view/theme"; @Injectable({ - providedIn: 'root' + providedIn: "root" }) export class SettingsService { - appsettings!: Appsettings; + appSettings!: AppSettings; + versionSettings!: VersionSettings; constructor( private http: HttpClient - ) { } + ) { + } - loadSettings(): Promise { + loadSettings(version: boolean = false): Promise { return new Promise((resolve, reject) => { - this.http.get('../../assets/config.json') - .pipe(catchError(error => { - reject(error); - return throwError(() => error); - })).subscribe(settings => { - this.appsettings = settings; - resolve(settings); - }); + forkJoin([ + this.http.get("../../assets/config.json") + .pipe(catchError(error => { + reject(error); + return throwError(() => error); + })), + this.http.get("../../assets/version.json") + .pipe(catchError(error => { + reject(error); + return throwError(() => error); + })) + ]).subscribe(settings => { + this.appSettings = settings[0]; + this.versionSettings = settings[1]; + resolve({...settings[0], ...settings[1]}); + }); }); } public getApiURL(): string { - if (!this.appsettings || !this.appsettings.ApiURL) { - console.error('ApiUrl is not set!'); + if (!this.appSettings || !this.appSettings.ApiURL) { + console.error("ApiUrl is not set!"); return ""; } - return this.appsettings.ApiURL; + return this.appSettings.ApiURL; } public getPrivacyURL(): string { - if (!this.appsettings || !this.appsettings.PrivacyURL) { - console.error('PrivacyURL is not set!'); + if (!this.appSettings || !this.appSettings.PrivacyURL) { + console.error("PrivacyURL is not set!"); return ""; } - return this.appsettings.PrivacyURL; + return this.appSettings.PrivacyURL; } public getImprintURL(): string { - if (!this.appsettings || !this.appsettings.ImprintURL) { - console.error('ImprintURL is not set!'); + if (!this.appSettings || !this.appSettings.ImprintURL) { + console.error("ImprintURL is not set!"); return ""; } - return this.appsettings.ImprintURL; + return this.appSettings.ImprintURL; } public getWebVersion(): SoftwareVersion | null { - if (!this.appsettings || !this.appsettings.WebVersion) { - console.error('WebVersion is not set!'); + if (!this.versionSettings || !this.versionSettings.WebVersion) { + console.error("WebVersion is not set!"); return null; } return new SoftwareVersion( - this.appsettings.WebVersion.Major, - this.appsettings.WebVersion.Minor, - this.appsettings.WebVersion.Micro + this.versionSettings.WebVersion.Major, + this.versionSettings.WebVersion.Minor, + this.versionSettings.WebVersion.Micro ); } public getThemes(): Theme[] | null { - if (!this.appsettings || !this.appsettings.Themes) { - console.error('Themes is not set!'); + if (!this.appSettings || !this.appSettings.Themes) { + console.error("Themes is not set!"); return null; } - return this.appsettings.Themes; + return this.appSettings.Themes; } } diff --git a/kdb-web/src/assets/version.json b/kdb-web/src/assets/version.json new file mode 100644 index 00000000..8d4c9ae3 --- /dev/null +++ b/kdb-web/src/assets/version.json @@ -0,0 +1,7 @@ +{ + "WebVersion": { + "Major": "1", + "Minor": "0", + "Micro": "dev294_frontend_version" + } +} \ No newline at end of file diff --git a/kdb-web/update-version.ts b/kdb-web/update-version.ts index 7e3c56c8..57c90424 100644 --- a/kdb-web/update-version.ts +++ b/kdb-web/update-version.ts @@ -1,8 +1,8 @@ -import { Appsettings } from "./src/app/models/config/appsettings"; +import { VersionSettings } from "./src/app/models/config/app-settings"; import { SoftwareVersion } from "./src/app/models/config/software-version"; import fs from "fs"; -const jsonFilePath = "./src/assets/config.json"; +const jsonFilePath = "./src/assets/version.json"; function Main(): void { getVersion() @@ -38,13 +38,13 @@ async function getVersion(): Promise { } } else if (branch.startsWith("#")) { const fs = require("fs"); - const config: Appsettings = JSON.parse(fs.readFileSync(jsonFilePath, "utf-8")); + const config: VersionSettings = JSON.parse(fs.readFileSync(jsonFilePath, "utf-8")); major = config.WebVersion.Major; minor = config.WebVersion.Minor; micro = `dev${branch.split("#")[1]}`; } else { const fs = require("fs"); - const config: Appsettings = JSON.parse(fs.readFileSync(jsonFilePath, "utf-8")); + const config: VersionSettings = JSON.parse(fs.readFileSync(jsonFilePath, "utf-8")); major = config.WebVersion.Major; minor = config.WebVersion.Minor; micro = config.WebVersion.Micro; @@ -59,7 +59,7 @@ async function setVersion(version: SoftwareVersion) { if (err) { throw err; } - const settings: Appsettings = JSON.parse(data); + const settings: VersionSettings = JSON.parse(data); settings.WebVersion = version; fs.writeFile(jsonFilePath, JSON.stringify(settings, null, 4), "utf8", () => { }); -- 2.45.2 From 05a2ea9b1885cd9df50c348d093dee3775bfd60e Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 19 Jul 2023 10:49:37 +0200 Subject: [PATCH 041/127] Added migration for config in wi #127 --- kdb-bot/.cpl/schematic_migration.py | 55 +++++++++++++++++++ kdb-bot/.cpl/schematic_query.py | 2 +- .../src/bot/startup_migration_extension.py | 2 + .../configuration/feature_flags_enum.py | 1 + .../configuration/feature_flags_settings.py | 1 + .../bot_data/migration/config_migration.py | 33 +++++++++++ 6 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 kdb-bot/.cpl/schematic_migration.py create mode 100644 kdb-bot/src/bot_data/migration/config_migration.py 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/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_core/configuration/feature_flags_enum.py b/kdb-bot/src/bot_core/configuration/feature_flags_enum.py index 37a579fe..c2a0cf6c 100644 --- a/kdb-bot/src/bot_core/configuration/feature_flags_enum.py +++ b/kdb-bot/src/bot_core/configuration/feature_flags_enum.py @@ -20,3 +20,4 @@ class FeatureFlagsEnum(Enum): api_only = "ApiOnly" presence = "Presence" version_in_presence = "VersionInPresence" + config_in_wi = "ConfigInWI" 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..469532bc 100644 --- a/kdb-bot/src/bot_core/configuration/feature_flags_settings.py +++ b/kdb-bot/src/bot_core/configuration/feature_flags_settings.py @@ -28,6 +28,7 @@ class FeatureFlagsSettings(ConfigurationModelABC): 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 + FeatureFlagsEnum.config_in_wi.value: True, # 19.07.2023 #127 } def get_flag(self, key: FeatureFlagsEnum) -> bool: 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..abdb6e5b --- /dev/null +++ b/kdb-bot/src/bot_data/migration/config_migration.py @@ -0,0 +1,33 @@ +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 upgrade(self): + self._logger.debug(__name__, "Running upgrade") + + # self._cursor.execute( + # str( + # f""" + # CREATE TABLE IF NOT EXISTS `Config` ( + # `Id` BIGINT NOT NULL AUTO_INCREMENT, + # `CreatedAt` DATETIME(6), + # `LastModifiedAt` DATETIME(6), + # PRIMARY KEY(`Id`) + # ); + # """ + # ) + # ) + + def downgrade(self): + self._logger.debug(__name__, "Running downgrade") + # self._cursor.execute("DROP TABLE `Config`;") -- 2.45.2 From c782c11b6dfc9785a03f939a6efe7364175448c3 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 19 Jul 2023 12:15:57 +0200 Subject: [PATCH 042/127] Removed from_dict from settings stuff #127 --- kdb-bot/src/bot/bot.json | 11 +-- kdb-bot/src/bot/config | 2 +- .../src/bot_api/configuration/api_settings.py | 20 ++---- .../configuration/authentication_settings.py | 34 ++++----- .../discord_authentication_settings.py | 33 ++++----- .../configuration/frontend_settings.py | 14 +--- .../bot_api/configuration/version_settings.py | 49 ------------- .../configuration/bot_logging_settings.py | 9 ++- .../bot_core/configuration/bot_settings.py | 33 ++------- .../configuration/feature_flags_settings.py | 19 ++--- .../configuration/file_logging_settings.py | 8 --- .../bot_core/configuration/server_settings.py | 15 +--- .../configuration/base_server_settings.py | 72 ++++++++----------- .../base/configuration/base_settings.py | 22 ++---- .../boot_log/boot_log_on_ready_event.py | 6 -- .../configuration/boot_log_server_settings.py | 17 +---- .../configuration/boot_log_settings.py | 22 ++---- .../configuration/default_level_settings.py | 37 ++++------ .../permission_server_settings.py | 23 ++---- .../configuration/permission_settings.py | 22 ++---- 20 files changed, 126 insertions(+), 342 deletions(-) delete mode 100644 kdb-bot/src/bot_api/configuration/version_settings.py 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..42b9291f 160000 --- a/kdb-bot/src/bot/config +++ b/kdb-bot/src/bot/config @@ -1 +1 @@ -Subproject commit 440fb3bd353dce31a2408c977a3168e3cfc32f9a +Subproject commit 42b9291f1a8484b3866a2e013b0f980aea093c4b 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/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 index dc6b8bbf..431bf9f0 100644 --- a/kdb-bot/src/bot_core/configuration/bot_settings.py +++ b/kdb-bot/src/bot_core/configuration/bot_settings.py @@ -1,7 +1,7 @@ from cpl_core.configuration import ConfigurationModelABC +from cpl_core.utils.json_processor import JSONProcessor from cpl_query.extension import List -from bot_api.json_processor import JSONProcessor from bot_core.configuration.server_settings import ServerSettings @@ -12,7 +12,7 @@ class BotSettings(ConfigurationModelABC): wait_for_restart: int = 2, wait_for_shutdown: int = 2, cache_max_messages: int = 1000, - server_settings: dict = None, + **kwargs: dict, ): ConfigurationModelABC.__init__(self) @@ -23,8 +23,9 @@ class BotSettings(ConfigurationModelABC): self._servers: List[ServerSettings] = List(ServerSettings) - if server_settings is not None: - self._servers_from_dict(server_settings) + for s in kwargs: + kwargs[s]["Id"] = s + self._servers.append(JSONProcessor.process(ServerSettings, kwargs[s])) @property def servers(self) -> List[ServerSettings]: @@ -53,27 +54,3 @@ class BotSettings(ConfigurationModelABC): 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_settings.py b/kdb-bot/src/bot_core/configuration/feature_flags_settings.py index 469532bc..65985966 100644 --- a/kdb-bot/src/bot_core/configuration/feature_flags_settings.py +++ b/kdb-bot/src/bot_core/configuration/feature_flags_settings.py @@ -1,13 +1,10 @@ -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): + def __init__(self, **kwargs: dict): ConfigurationModelABC.__init__(self) self._flags = { @@ -31,6 +28,12 @@ class FeatureFlagsSettings(ConfigurationModelABC): FeatureFlagsEnum.config_in_wi.value: True, # 19.07.2023 #127 } + 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: return False @@ -41,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 index ca382886..843cbc70 100644 --- a/kdb-bot/src/bot_core/configuration/server_settings.py +++ b/kdb-bot/src/bot_core/configuration/server_settings.py @@ -10,9 +10,9 @@ class ServerSettings(ConfigurationModelABC): ): ConfigurationModelABC.__init__(self) - self._id: int = id - self._message_delete_timer: int = message_delete_timer - self._notification_chat_id: int = notification_chat_id + self._id: int = 0 if id is None else id + self._message_delete_timer: int = 0 if message_delete_timer is None else message_delete_timer + self._notification_chat_id: int = 0 if notification_chat_id is None else notification_chat_id @property def id(self) -> int: @@ -25,12 +25,3 @@ class ServerSettings(ConfigurationModelABC): @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/modules/base/configuration/base_server_settings.py b/kdb-bot/src/modules/base/configuration/base_server_settings.py index 8bd987b4..ec0a2758 100644 --- a/kdb-bot/src/modules/base/configuration/base_server_settings.py +++ b/kdb-bot/src/modules/base/configuration/base_server_settings.py @@ -1,28 +1,41 @@ -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): + def __init__( + self, + id: int = None, + max_voice_state_hours: int = None, + xp_per_message: int = None, + xp_per_reaction: int = None, + max_message_xp_per_hour: int = None, + xp_per_ontime_hour: int = None, + xp_per_event_participation: int = None, + xp_per_achievement: int = None, + afk_channel_ids: List = None, + afk_command_channel_id: int = None, + help_command_reference_url: str = None, + help_voice_channel_id: int = None, + team_channel_id: int = None, + ping_urls: list = None, + ): 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) + self._id = 0 if id is None else id + self._max_voice_state_hours = 0 if max_voice_state_hours is None else max_voice_state_hours + self._xp_per_message = 0 if xp_per_message is None else xp_per_message + self._xp_per_reaction = 0 if xp_per_reaction is None else xp_per_reaction + self._max_message_xp_per_hour = 0 if max_message_xp_per_hour is None else max_message_xp_per_hour + self._xp_per_ontime_hour = 0 if xp_per_ontime_hour is None else xp_per_ontime_hour + self._xp_per_event_participation = 0 if xp_per_event_participation is None else xp_per_event_participation + self._xp_per_achievement = 0 if xp_per_achievement is None else xp_per_achievement + self._afk_channel_ids = List(int) if afk_channel_ids is None else List(int, afk_channel_ids) + self._afk_command_channel_id = 0 if afk_command_channel_id is None else afk_command_channel_id + self._help_command_reference_url = "" if help_command_reference_url is None else help_command_reference_url + self._help_voice_channel_id = 0 if help_voice_channel_id is None else help_voice_channel_id + self._team_channel_id = 0 if team_channel_id is None else team_channel_id + self._ping_urls = List(str) if ping_urls is None else List(str, ping_urls) @property def id(self) -> int: @@ -79,26 +92,3 @@ class BaseServerSettings(ConfigurationModelABC): @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 index 0c74132c..e3f24ac4 100644 --- a/kdb-bot/src/modules/base/configuration/base_settings.py +++ b/kdb-bot/src/modules/base/configuration/base_settings.py @@ -1,31 +1,19 @@ -import traceback - from cpl_core.configuration import ConfigurationModelABC -from cpl_core.console import Console +from cpl_core.utils.json_processor import JSONProcessor from cpl_query.extension import List from modules.base.configuration.base_server_settings import BaseServerSettings class BaseSettings(ConfigurationModelABC): - def __init__(self): + def __init__(self, **kwargs: dict): ConfigurationModelABC.__init__(self) self._servers: List[BaseServerSettings] = List() + for s in kwargs: + kwargs[s]["Id"] = s + self._servers.append(JSONProcessor.process(BaseServerSettings, kwargs[s])) @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/boot_log/boot_log_on_ready_event.py b/kdb-bot/src/modules/boot_log/boot_log_on_ready_event.py index 58c2b5c4..07344bbd 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,7 +8,6 @@ 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, ) @@ -58,11 +57,6 @@ 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: self._logger.error(__name__, f"Config {type(self).__name__}_{g.id} not found!") 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 index 148609af..f7e050ef 100644 --- 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 @@ -1,15 +1,12 @@ -import traceback - from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console class BootLogServerSettings(ConfigurationModelABC): - def __init__(self): + def __init__(self, id: int = None, login_message_channel_id: int = None): ConfigurationModelABC.__init__(self) - self._id: int = 0 - self._login_message_channel_id: int = 0 + self._id: int = 0 if id is None else id + self._login_message_channel_id: int = 0 if login_message_channel_id is None else login_message_channel_id @property def id(self) -> int: @@ -18,11 +15,3 @@ class BootLogServerSettings(ConfigurationModelABC): @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 index d06ed5fb..415d5899 100644 --- a/kdb-bot/src/modules/boot_log/configuration/boot_log_settings.py +++ b/kdb-bot/src/modules/boot_log/configuration/boot_log_settings.py @@ -1,7 +1,5 @@ -import traceback - from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console +from cpl_core.utils.json_processor import JSONProcessor from cpl_query.extension import List from modules.boot_log.configuration.boot_log_server_settings import ( @@ -10,24 +8,14 @@ from modules.boot_log.configuration.boot_log_server_settings import ( class BootLogSettings(ConfigurationModelABC): - def __init__(self): + def __init__(self, **kwargs: dict): ConfigurationModelABC.__init__(self) self._servers: List[BootLogServerSettings] = List() + for s in kwargs: + kwargs[s]["Id"] = s + self._servers.append(JSONProcessor.process(BootLogServerSettings, kwargs[s])) @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/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/permission/configuration/permission_server_settings.py b/kdb-bot/src/modules/permission/configuration/permission_server_settings.py index 1ffdfdf7..6e928f36 100644 --- a/kdb-bot/src/modules/permission/configuration/permission_server_settings.py +++ b/kdb-bot/src/modules/permission/configuration/permission_server_settings.py @@ -1,16 +1,13 @@ -import traceback - from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console class PermissionServerSettings(ConfigurationModelABC): - def __init__(self): + def __init__(self, id: int = None, admin_role_ids: list = None, moderator_role_ids: list = None): ConfigurationModelABC.__init__(self) - self._id: int = 0 - self._admin_roles: list[int] = [] - self._moderator_roles: list[int] = [] + self._id: int = 0 if id is None else id + self._admin_roles: list[int] = [] if admin_role_ids is None else admin_role_ids + self._moderator_roles: list[int] = [] if moderator_role_ids is None else moderator_role_ids @property def id(self) -> int: @@ -23,15 +20,3 @@ class PermissionServerSettings(ConfigurationModelABC): @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 index 532c592a..8ce4ad7b 100644 --- a/kdb-bot/src/modules/permission/configuration/permission_settings.py +++ b/kdb-bot/src/modules/permission/configuration/permission_settings.py @@ -1,7 +1,5 @@ -import traceback - from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.console import Console +from cpl_core.utils.json_processor import JSONProcessor from cpl_query.extension import List from modules.permission.configuration.permission_server_settings import ( @@ -10,24 +8,14 @@ from modules.permission.configuration.permission_server_settings import ( class PermissionSettings(ConfigurationModelABC): - def __init__(self): + def __init__(self, **kwargs: dict): ConfigurationModelABC.__init__(self) self._servers: List[PermissionServerSettings] = List() + for s in kwargs: + kwargs[s]["Id"] = s + self._servers.append(JSONProcessor.process(PermissionServerSettings, kwargs[s])) @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()}") -- 2.45.2 From da3538a836e1e742e442ec260c9623b03c3cd99d Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 19 Jul 2023 13:03:38 +0200 Subject: [PATCH 043/127] Added config migration #127 --- .../bot_data/migration/config_migration.py | 146 ++++++++++++++++-- .../db_history_scripts/config/server.sql | 117 ++++++++++++++ .../config/server_afk_channels.sql | 57 +++++++ .../config/server_team_roles.sql | 62 ++++++++ .../db_history_scripts/config/technician.sql | 67 ++++++++ .../config/technician_ids.sql | 52 +++++++ .../config/technician_ping_urls.sql | 52 +++++++ 7 files changed, 540 insertions(+), 13 deletions(-) create mode 100644 kdb-bot/src/bot_data/migration/db_history_scripts/config/server.sql create mode 100644 kdb-bot/src/bot_data/migration/db_history_scripts/config/server_afk_channels.sql create mode 100644 kdb-bot/src/bot_data/migration/db_history_scripts/config/server_team_roles.sql create mode 100644 kdb-bot/src/bot_data/migration/db_history_scripts/config/technician.sql create mode 100644 kdb-bot/src/bot_data/migration/db_history_scripts/config/technician_ids.sql create mode 100644 kdb-bot/src/bot_data/migration/db_history_scripts/config/technician_ping_urls.sql diff --git a/kdb-bot/src/bot_data/migration/config_migration.py b/kdb-bot/src/bot_data/migration/config_migration.py index abdb6e5b..0370cbb4 100644 --- a/kdb-bot/src/bot_data/migration/config_migration.py +++ b/kdb-bot/src/bot_data/migration/config_migration.py @@ -1,3 +1,5 @@ +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 @@ -12,22 +14,140 @@ class ConfigMigration(MigrationABC): 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._cursor.execute( - # str( - # f""" - # CREATE TABLE IF NOT EXISTS `Config` ( - # `Id` BIGINT NOT NULL AUTO_INCREMENT, - # `CreatedAt` DATETIME(6), - # `LastModifiedAt` DATETIME(6), - # PRIMARY KEY(`Id`) - # ); - # """ - # ) - # ) + 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") - # self._cursor.execute("DROP TABLE `Config`;") + + 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..ed2be14a --- /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.UserId, + 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.UserId, + 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..fbd14d7b --- /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.UserId, + 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.UserId, + 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..bbc1aed3 --- /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.UserId, + 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.UserId, + 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..2ebf8500 --- /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.UserId, + 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.UserId, + 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..3d13de75 --- /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.UserId, + 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.UserId, + 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..fdab3226 --- /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.UserId, + 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.UserId, + OLD.URL, + TRUE, + OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file -- 2.45.2 From a03ddf3fc2c735ef767521bd27bb42d8ab9135f2 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 24 Jul 2023 18:10:44 +0200 Subject: [PATCH 044/127] Added sql for cfg in wi migration #127 --- .../bot_data/migration/db_history_scripts/config/server.sql | 4 ++-- .../db_history_scripts/config/server_afk_channels.sql | 4 ++-- .../migration/db_history_scripts/config/server_team_roles.sql | 4 ++-- .../migration/db_history_scripts/config/technician.sql | 4 ++-- .../migration/db_history_scripts/config/technician_ids.sql | 4 ++-- .../db_history_scripts/config/technician_ping_urls.sql | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) 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 index ed2be14a..e9c327b8 100644 --- 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 @@ -47,7 +47,7 @@ BEGIN `DateTo` ) VALUES ( - OLD.UserId, + OLD.Id, OLD.MessageDeleteTimer, OLD.NotificationChatId, OLD.MaxVoiceStateHours, @@ -95,7 +95,7 @@ BEGIN `DateTo` ) VALUES ( - OLD.UserId, + OLD.Id, OLD.MessageDeleteTimer, OLD.NotificationChatId, OLD.MaxVoiceStateHours, 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 index fbd14d7b..4dfd7e31 100644 --- 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 @@ -23,7 +23,7 @@ BEGIN `DateTo` ) VALUES ( - OLD.UserId, + OLD.Id, OLD.ChannelId, OLD.ServerId, OLD.LastModifiedAt, @@ -47,7 +47,7 @@ BEGIN `DateTo` ) VALUES ( - OLD.UserId, + OLD.Id, OLD.ChannelId, OLD.ServerId, TRUE, 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 index bbc1aed3..8733da4d 100644 --- 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 @@ -25,7 +25,7 @@ BEGIN `DateTo` ) VALUES ( - OLD.UserId, + OLD.Id, OLD.RoleId, OLD.TeamMemberType, OLD.ServerId, @@ -51,7 +51,7 @@ BEGIN `DateTo` ) VALUES ( - OLD.UserId, + OLD.Id, OLD.RoleId, OLD.TeamMemberType, OLD.ServerId, 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 index 2ebf8500..50907c2f 100644 --- 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 @@ -27,7 +27,7 @@ BEGIN `DateTo` ) VALUES ( - OLD.UserId, + OLD.Id, OLD.HelpCommandReferenceUrl, OLD.WaitForRestart, OLD.WaitForShutdown, @@ -55,7 +55,7 @@ BEGIN `DateTo` ) VALUES ( - OLD.UserId, + OLD.Id, OLD.HelpCommandReferenceUrl, OLD.WaitForRestart, OLD.WaitForShutdown, 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 index 3d13de75..251d4b30 100644 --- 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 @@ -21,7 +21,7 @@ BEGIN `DateTo` ) VALUES ( - OLD.UserId, + OLD.Id, OLD.TechnicianId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) @@ -43,7 +43,7 @@ BEGIN `DateTo` ) VALUES ( - OLD.UserId, + OLD.Id, OLD.TechnicianId, TRUE, OLD.LastModifiedAt, 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 index fdab3226..d61c3cce 100644 --- 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 @@ -21,7 +21,7 @@ BEGIN `DateTo` ) VALUES ( - OLD.UserId, + OLD.Id, OLD.URL, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) @@ -43,7 +43,7 @@ BEGIN `DateTo` ) VALUES ( - OLD.UserId, + OLD.Id, OLD.URL, TRUE, OLD.LastModifiedAt, -- 2.45.2 From 9671090385c66560a6fdf7903360f970f5e890e5 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 26 Jul 2023 12:10:24 +0200 Subject: [PATCH 045/127] Added technician config repo #127 --- kdb-bot/.cpl/schematic_db_table.py | 100 +++++++++++++ .../abc/technician_config_repository_abc.py | 25 ++++ .../src/bot_data/model/technician_config.py | 132 ++++++++++++++++++ .../bot_data/model/technician_id_config.py | 75 ++++++++++ .../model/technician_ping_url_config.py | 75 ++++++++++ .../technician_config_repository_service.py | 67 +++++++++ 6 files changed, 474 insertions(+) create mode 100644 kdb-bot/.cpl/schematic_db_table.py create mode 100644 kdb-bot/src/bot_data/abc/technician_config_repository_abc.py create mode 100644 kdb-bot/src/bot_data/model/technician_config.py create mode 100644 kdb-bot/src/bot_data/model/technician_id_config.py create mode 100644 kdb-bot/src/bot_data/model/technician_ping_url_config.py create mode 100644 kdb-bot/src/bot_data/service/technician_config_repository_service.py 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/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..377103fb --- /dev/null +++ b/kdb-bot/src/bot_data/abc/technician_config_repository_abc.py @@ -0,0 +1,25 @@ +from abc import ABC, abstractmethod + +from bot_data.model.technician_config import TechnicianConfig + + +class TechnicianConfigRepositoryABC(ABC): + @abstractmethod + def __init__(self): + 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 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..b90cb493 --- /dev/null +++ b/kdb-bot/src/bot_data/model/technician_config.py @@ -0,0 +1,132 @@ +from datetime import datetime + +from cpl_core.database import TableABC +from cpl_query.extension import List + + +class TechnicianConfig(TableABC): + 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 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_id_config.py b/kdb-bot/src/bot_data/model/technician_id_config.py new file mode 100644 index 00000000..ed9c51cc --- /dev/null +++ b/kdb-bot/src/bot_data/model/technician_id_config.py @@ -0,0 +1,75 @@ +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 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 `Id` = {self._id}; + """ + ) 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..b9504f5c --- /dev/null +++ b/kdb-bot/src/bot_data/model/technician_ping_url_config.py @@ -0,0 +1,75 @@ +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 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 `Id` = {self._id}; + """ + ) 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..de5ea2f2 --- /dev/null +++ b/kdb-bot/src/bot_data/service/technician_config_repository_service.py @@ -0,0 +1,67 @@ +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 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) -- 2.45.2 From 23757bc841b66e328b078526edd28e8879d47fba Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 26 Jul 2023 12:14:47 +0200 Subject: [PATCH 046/127] Improved technician config repo #127 --- .../abc/technician_config_repository_abc.py | 26 +++++++++++++++++++ .../technician_config_repository_service.py | 24 +++++++++++++++++ 2 files changed, 50 insertions(+) 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 index 377103fb..1751cbe9 100644 --- a/kdb-bot/src/bot_data/abc/technician_config_repository_abc.py +++ b/kdb-bot/src/bot_data/abc/technician_config_repository_abc.py @@ -1,6 +1,8 @@ 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): @@ -23,3 +25,27 @@ class TechnicianConfigRepositoryABC(ABC): @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/service/technician_config_repository_service.py b/kdb-bot/src/bot_data/service/technician_config_repository_service.py index de5ea2f2..bd3728d5 100644 --- a/kdb-bot/src/bot_data/service/technician_config_repository_service.py +++ b/kdb-bot/src/bot_data/service/technician_config_repository_service.py @@ -65,3 +65,27 @@ class TechnicianConfigRepositoryService(TechnicianConfigRepositoryABC): 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) -- 2.45.2 From 71f1f972c9226e4efbf49b72419fa2a5a3877463 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 6 Aug 2023 10:24:05 +0200 Subject: [PATCH 047/127] Added technician config seeder #127 --- kdb-bot/src/bot_data/abc/data_seeder_abc.py | 2 +- .../abc/technician_config_repository_abc.py | 4 ++ kdb-bot/src/bot_data/data_module.py | 6 +++ .../src/bot_data/model/technician_config.py | 2 +- .../bot_data/model/technician_id_config.py | 2 +- .../model/technician_ping_url_config.py | 2 +- .../technician_config_repository_service.py | 6 +++ .../service/technician_config_seeder.py | 48 +++++++++++++++++++ 8 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 kdb-bot/src/bot_data/service/technician_config_seeder.py 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/technician_config_repository_abc.py b/kdb-bot/src/bot_data/abc/technician_config_repository_abc.py index 1751cbe9..25c88d96 100644 --- a/kdb-bot/src/bot_data/abc/technician_config_repository_abc.py +++ b/kdb-bot/src/bot_data/abc/technician_config_repository_abc.py @@ -10,6 +10,10 @@ class TechnicianConfigRepositoryABC(ABC): def __init__(self): pass + @abstractmethod + def does_technician_config_exists(self) -> bool: + pass + @abstractmethod def get_technician_config(self) -> TechnicianConfig: pass diff --git a/kdb-bot/src/bot_data/data_module.py b/kdb-bot/src/bot_data/data_module.py index fd571abb..0ef436a2 100644 --- a/kdb-bot/src/bot_data/data_module.py +++ b/kdb-bot/src/bot_data/data_module.py @@ -10,10 +10,12 @@ 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_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 @@ -36,6 +38,8 @@ from bot_data.service.known_user_repository_service import KnownUserRepositorySe from bot_data.service.level_repository_service import LevelRepositoryService from bot_data.service.seeder_service import SeederService 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 +84,7 @@ 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(SeederService) + services.add_transient(DataSeederABC, TechnicianConfigSeeder) diff --git a/kdb-bot/src/bot_data/model/technician_config.py b/kdb-bot/src/bot_data/model/technician_config.py index b90cb493..302d8c1e 100644 --- a/kdb-bot/src/bot_data/model/technician_config.py +++ b/kdb-bot/src/bot_data/model/technician_config.py @@ -104,7 +104,7 @@ class TechnicianConfig(TableABC): '{self._help_command_reference_url}', {self._wait_for_restart}, {self._wait_for_shutdown}, - {self._cache_max_messages}, + {self._cache_max_messages} ); """ ) diff --git a/kdb-bot/src/bot_data/model/technician_id_config.py b/kdb-bot/src/bot_data/model/technician_id_config.py index ed9c51cc..fcf0d83d 100644 --- a/kdb-bot/src/bot_data/model/technician_id_config.py +++ b/kdb-bot/src/bot_data/model/technician_id_config.py @@ -50,7 +50,7 @@ class TechnicianIdConfig(TableABC): INSERT INTO `CFG_TechnicianIds` ( `TechnicianId` ) VALUES ( - '{self._technician_id}', + '{self._technician_id}' ); """ ) 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 index b9504f5c..69d57965 100644 --- a/kdb-bot/src/bot_data/model/technician_ping_url_config.py +++ b/kdb-bot/src/bot_data/model/technician_ping_url_config.py @@ -50,7 +50,7 @@ class TechnicianPingUrlConfig(TableABC): INSERT INTO `CFG_TechnicianPingUrls` ( `URL` ) VALUES ( - '{self._ping_url}', + '{self._ping_url}' ); """ ) 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 index bd3728d5..3e1354cb 100644 --- a/kdb-bot/src/bot_data/service/technician_config_repository_service.py +++ b/kdb-bot/src/bot_data/service/technician_config_repository_service.py @@ -48,6 +48,12 @@ class TechnicianConfigRepositoryService(TechnicianConfigRepositoryABC): 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] 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..44ed44e6 --- /dev/null +++ b/kdb-bot/src/bot_data/service/technician_config_seeder.py @@ -0,0 +1,48 @@ +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 not self._technician_config.does_technician_config_exists(): + 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) -- 2.45.2 From ec1ce4adef3b01f868fe1438c256dd880934bc47 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 6 Aug 2023 17:52:13 +0200 Subject: [PATCH 048/127] Changed config loading from file to db #127 --- kdb-bot/cpl-workspace.json | 1 + kdb-bot/src/bot/config | 2 +- .../src/bot/extension/init_bot_extension.py | 4 +- kdb-bot/src/bot/main.py | 2 + kdb-bot/src/bot/module_list.py | 4 +- kdb-bot/src/bot/startup_settings_extension.py | 12 +- kdb-bot/src/bot_core/abc/client_utils_abc.py | 4 +- .../bot_core/configuration/bot_settings.py | 56 ----- .../configuration/feature_flags_enum.py | 2 +- .../configuration/feature_flags_settings.py | 42 ++-- .../bot_core/configuration/server_settings.py | 27 --- .../bot_core/service/client_utils_service.py | 4 +- .../service/data_integrity_service.py | 6 +- .../src/bot_core/service/message_service.py | 6 +- .../abc/server_config_repository_abc.py | 55 +++++ kdb-bot/src/bot_data/data_module.py | 5 + .../model/server_afk_channel_ids_config.py | 76 +++++++ kdb-bot/src/bot_data/model/server_config.py | 205 ++++++++++++++++++ .../model/server_team_role_ids_config.py | 87 ++++++++ .../bot_data/model/team_member_type_enum.py | 6 + .../src/bot_data/model/technician_config.py | 3 +- .../server_config_repository_service.py | 118 ++++++++++ .../bot_data/service/server_config_seeder.py | 62 ++++++ .../service/technician_config_seeder.py | 33 +-- .../user_joined_game_server_mutation.py | 10 +- .../achievements/achievement_service.py | 7 +- kdb-bot/src/modules/base/abc/__init__.py | 26 --- .../src/modules/base/abc/base_helper_abc.py | 12 - kdb-bot/src/modules/base/base_module.py | 3 - .../src/modules/base/command/afk_command.py | 3 +- .../src/modules/base/command/help_command.py | 3 +- .../src/modules/base/command/ping_command.py | 11 +- .../src/modules/base/command/purge_command.py | 4 +- .../modules/base/configuration/__init__.py | 26 --- .../configuration/base_server_settings.py | 94 -------- .../base/configuration/base_settings.py | 19 -- .../events/base_on_command_error_event.py | 8 +- .../base/events/base_on_command_event.py | 9 +- .../base/events/base_on_member_join_event.py | 5 - .../events/base_on_member_remove_event.py | 5 +- .../events/base_on_message_delete_event.py | 6 +- .../base/events/base_on_message_event.py | 7 +- .../base_on_voice_state_update_event.py | 9 +- ...n_voice_state_update_event_help_channel.py | 7 +- ...tate_update_event_scheduled_event_bonus.py | 7 +- .../src/modules/base/forms/bug_report_form.py | 11 +- .../src/modules/base/forms/complaint_form.py | 10 +- .../base/helper/base_reaction_handler.py | 10 +- .../base/service/base_helper_service.py | 13 -- .../base/service/user_warnings_service.py | 6 +- .../boot_log/boot_log_on_ready_event.py | 10 +- kdb-bot/src/modules/config/__init__.py | 1 + kdb-bot/src/modules/config/config.json | 46 ++++ .../src/modules/config/config_extension.py | 24 ++ kdb-bot/src/modules/config/config_module.py | 20 ++ kdb-bot/src/modules/config/events/__init__.py | 1 + .../config/events/config_on_ready_event.py | 35 +++ .../modules/level/service/level_service.py | 3 +- .../permission/service/permission_service.py | 28 ++- .../technician/command/restart_command.py | 3 - .../technician/command/shutdown_command.py | 5 +- .../modules/technician/technician_module.py | 3 - 62 files changed, 872 insertions(+), 460 deletions(-) delete mode 100644 kdb-bot/src/bot_core/configuration/bot_settings.py delete mode 100644 kdb-bot/src/bot_core/configuration/server_settings.py create mode 100644 kdb-bot/src/bot_data/abc/server_config_repository_abc.py create mode 100644 kdb-bot/src/bot_data/model/server_afk_channel_ids_config.py create mode 100644 kdb-bot/src/bot_data/model/server_config.py create mode 100644 kdb-bot/src/bot_data/model/server_team_role_ids_config.py create mode 100644 kdb-bot/src/bot_data/model/team_member_type_enum.py create mode 100644 kdb-bot/src/bot_data/service/server_config_repository_service.py create mode 100644 kdb-bot/src/bot_data/service/server_config_seeder.py delete mode 100644 kdb-bot/src/modules/base/abc/__init__.py delete mode 100644 kdb-bot/src/modules/base/abc/base_helper_abc.py delete mode 100644 kdb-bot/src/modules/base/configuration/__init__.py delete mode 100644 kdb-bot/src/modules/base/configuration/base_server_settings.py delete mode 100644 kdb-bot/src/modules/base/configuration/base_settings.py delete mode 100644 kdb-bot/src/modules/base/service/base_helper_service.py create mode 100644 kdb-bot/src/modules/config/__init__.py create mode 100644 kdb-bot/src/modules/config/config.json create mode 100644 kdb-bot/src/modules/config/config_extension.py create mode 100644 kdb-bot/src/modules/config/config_module.py create mode 100644 kdb-bot/src/modules/config/events/__init__.py create mode 100644 kdb-bot/src/modules/config/events/config_on_ready_event.py 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/config b/kdb-bot/src/bot/config index 42b9291f..4264ba15 160000 --- a/kdb-bot/src/bot/config +++ b/kdb-bot/src/bot/config @@ -1 +1 @@ -Subproject commit 42b9291f1a8484b3866a2e013b0f980aea093c4b +Subproject commit 4264ba15970a28f8a50c888bbf635a15c438bcf9 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_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_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_settings.py b/kdb-bot/src/bot_core/configuration/bot_settings.py deleted file mode 100644 index 431bf9f0..00000000 --- a/kdb-bot/src/bot_core/configuration/bot_settings.py +++ /dev/null @@ -1,56 +0,0 @@ -from cpl_core.configuration import ConfigurationModelABC -from cpl_core.utils.json_processor import JSONProcessor -from cpl_query.extension import List - -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, - **kwargs: dict, - ): - 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) - - for s in kwargs: - kwargs[s]["Id"] = s - self._servers.append(JSONProcessor.process(ServerSettings, kwargs[s])) - - @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 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 c2a0cf6c..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,8 +16,8 @@ class FeatureFlagsEnum(Enum): level_module = "LevelModule" moderator_module = "ModeratorModule" permission_module = "PermissionModule" + config_module = "ConfigModule" # features api_only = "ApiOnly" presence = "Presence" version_in_presence = "VersionInPresence" - config_in_wi = "ConfigInWI" 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 65985966..19aeb110 100644 --- a/kdb-bot/src/bot_core/configuration/feature_flags_settings.py +++ b/kdb-bot/src/bot_core/configuration/feature_flags_settings.py @@ -4,30 +4,30 @@ from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum class FeatureFlagsSettings(ConfigurationModelABC): + _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 - FeatureFlagsEnum.config_in_wi.value: True, # 19.07.2023 #127 - } - if len(kwargs.keys()) == 0: return 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 843cbc70..00000000 --- a/kdb-bot/src/bot_core/configuration/server_settings.py +++ /dev/null @@ -1,27 +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 = 0 if id is None else id - self._message_delete_timer: int = 0 if message_delete_timer is None else message_delete_timer - self._notification_chat_id: int = 0 if notification_chat_id is None else 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 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..78b64e73 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: @@ -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/server_config_repository_abc.py b/kdb-bot/src/bot_data/abc/server_config_repository_abc.py new file mode 100644 index 00000000..e6fd480c --- /dev/null +++ b/kdb-bot/src/bot_data/abc/server_config_repository_abc.py @@ -0,0 +1,55 @@ +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(self, server_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/data_module.py b/kdb-bot/src/bot_data/data_module.py index 0ef436a2..9c35713e 100644 --- a/kdb-bot/src/bot_data/data_module.py +++ b/kdb-bot/src/bot_data/data_module.py @@ -14,6 +14,7 @@ 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 @@ -37,6 +38,8 @@ 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 @@ -85,6 +88,8 @@ class DataModule(ModuleABC): 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/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..f567ccee --- /dev/null +++ b/kdb-bot/src/bot_data/model/server_afk_channel_ids_config.py @@ -0,0 +1,76 @@ +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}; + """ + ) + + @property + def insert_string(self) -> str: + return str( + f""" + INSERT INTO `CFG_ServerAFKChannelIds` ( + `RoleId`, + `ServerId` + ) VALUES ( + {self._channel_id}, + {self._server_id} + ); + """ + ) + + @property + def udpate_string(self) -> str: + return str( + f""" + UPDATE `CFG_ServerAFKChannelIds` + SET `RoleId` = {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 `Id` = {self._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..b962e221 --- /dev/null +++ b/kdb-bot/src/bot_data/model/server_config.py @@ -0,0 +1,205 @@ +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 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 afk_channel_ids(self) -> List[int]: + return self._afk_channel_ids + + @property + def team_role_ids(self) -> List[ServerTeamRoleIdsConfig]: + return self._team_role_ids + + @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}; + """ + ) + + @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_team_role_ids_config.py b/kdb-bot/src/bot_data/model/server_team_role_ids_config.py new file mode 100644 index 00000000..aee799fd --- /dev/null +++ b/kdb-bot/src/bot_data/model/server_team_role_ids_config.py @@ -0,0 +1,87 @@ +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 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}; + """ + ) + + @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 `Id` = {self._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 index 302d8c1e..062943d9 100644 --- a/kdb-bot/src/bot_data/model/technician_config.py +++ b/kdb-bot/src/bot_data/model/technician_config.py @@ -1,10 +1,11 @@ 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): +class TechnicianConfig(TableABC, ConfigurationModelABC): def __init__( self, help_command_reference_url: str, 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..3b069e71 --- /dev/null +++ b/kdb-bot/src/bot_data/service/server_config_repository_service.py @@ -0,0 +1,118 @@ +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_team_role_id: int) -> List[ServerTeamRoleIdsConfig]: + ids = List(ServerTeamRoleIdsConfig) + self._logger.trace( + __name__, f"Send SQL command: {ServerTeamRoleIdsConfig.get_select_by_id_string(server_team_role_id)}" + ) + results = self._context.select(ServerTeamRoleIdsConfig.get_select_by_id_string(server_team_role_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_team_role_id: int) -> List[int]: + urls = List(str) + self._logger.trace( + __name__, f"Send SQL command: {ServerAFKChannelIdsConfig.get_select_by_id_string(server_team_role_id)}" + ) + results = self._context.select(ServerAFKChannelIdsConfig.get_select_by_id_string(server_team_role_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[0]), + self._get_team_role_ids(result[0]), + 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(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 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_seeder.py b/kdb-bot/src/bot_data/service/technician_config_seeder.py index 44ed44e6..ce2be05d 100644 --- a/kdb-bot/src/bot_data/service/technician_config_seeder.py +++ b/kdb-bot/src/bot_data/service/technician_config_seeder.py @@ -24,25 +24,26 @@ class TechnicianConfigSeeder(DataSeederABC): async def seed(self): try: - if not self._technician_config.does_technician_config_exists(): - 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"]), - ) + if self._technician_config.does_technician_config_exists(): + return - self._technician_config.add_technician_config(config) - for technician in config.technician_ids: - self._technician_config.add_technician_id_config(TechnicianIdConfig(technician)) + 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"]), + ) - for url in config.ping_urls: - self._technician_config.add_technician_ping_url_config(TechnicianPingUrlConfig(url)) + self._technician_config.add_technician_config(config) + for technician in config.technician_ids: + self._technician_config.add_technician_id_config(TechnicianIdConfig(technician)) - self._db.save_changes() - self._logger.debug(__name__, "Seeded technician config") + 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/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/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 ec0a2758..00000000 --- a/kdb-bot/src/modules/base/configuration/base_server_settings.py +++ /dev/null @@ -1,94 +0,0 @@ -from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_query.extension import List - - -class BaseServerSettings(ConfigurationModelABC): - def __init__( - self, - id: int = None, - max_voice_state_hours: int = None, - xp_per_message: int = None, - xp_per_reaction: int = None, - max_message_xp_per_hour: int = None, - xp_per_ontime_hour: int = None, - xp_per_event_participation: int = None, - xp_per_achievement: int = None, - afk_channel_ids: List = None, - afk_command_channel_id: int = None, - help_command_reference_url: str = None, - help_voice_channel_id: int = None, - team_channel_id: int = None, - ping_urls: list = None, - ): - ConfigurationModelABC.__init__(self) - - self._id = 0 if id is None else id - self._max_voice_state_hours = 0 if max_voice_state_hours is None else max_voice_state_hours - self._xp_per_message = 0 if xp_per_message is None else xp_per_message - self._xp_per_reaction = 0 if xp_per_reaction is None else xp_per_reaction - self._max_message_xp_per_hour = 0 if max_message_xp_per_hour is None else max_message_xp_per_hour - self._xp_per_ontime_hour = 0 if xp_per_ontime_hour is None else xp_per_ontime_hour - self._xp_per_event_participation = 0 if xp_per_event_participation is None else xp_per_event_participation - self._xp_per_achievement = 0 if xp_per_achievement is None else xp_per_achievement - self._afk_channel_ids = List(int) if afk_channel_ids is None else List(int, afk_channel_ids) - self._afk_command_channel_id = 0 if afk_command_channel_id is None else afk_command_channel_id - self._help_command_reference_url = "" if help_command_reference_url is None else help_command_reference_url - self._help_voice_channel_id = 0 if help_voice_channel_id is None else help_voice_channel_id - self._team_channel_id = 0 if team_channel_id is None else team_channel_id - self._ping_urls = List(str) if ping_urls is None else List(str, ping_urls) - - @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 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 e3f24ac4..00000000 --- a/kdb-bot/src/modules/base/configuration/base_settings.py +++ /dev/null @@ -1,19 +0,0 @@ -from cpl_core.configuration import ConfigurationModelABC -from cpl_core.utils.json_processor import JSONProcessor -from cpl_query.extension import List - -from modules.base.configuration.base_server_settings import BaseServerSettings - - -class BaseSettings(ConfigurationModelABC): - def __init__(self, **kwargs: dict): - ConfigurationModelABC.__init__(self) - - self._servers: List[BaseServerSettings] = List() - for s in kwargs: - kwargs[s]["Id"] = s - self._servers.append(JSONProcessor.process(BaseServerSettings, kwargs[s])) - - @property - def servers(self) -> List[BaseServerSettings]: - return self._servers 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 07344bbd..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,9 +8,7 @@ from cpl_translation import TranslatePipe from discord import guild from bot_core.abc.message_service_abc import MessageServiceABC -from modules.boot_log.configuration.boot_log_server_settings import ( - BootLogServerSettings, -) +from bot_data.model.server_config import ServerConfig class BootLogOnReadyEvent(OnReadyABC): @@ -57,14 +55,14 @@ class BootLogOnReadyEvent(OnReadyABC): g: guild = g self._logger.debug(__name__, f"Server detected: {g.id}") - 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/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..614620c8 --- /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(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/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/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) -- 2.45.2 From 5c2c89ca45d58dbf29523359082a9172a46402ec Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 6 Aug 2023 17:53:32 +0200 Subject: [PATCH 049/127] Removed old settings #127 --- .../boot_log/configuration/__init__.py | 26 ------------------- .../configuration/boot_log_server_settings.py | 17 ------------ .../configuration/boot_log_settings.py | 21 --------------- .../permission/configuration/__init__.py | 26 ------------------- .../permission_server_settings.py | 22 ---------------- .../configuration/permission_settings.py | 21 --------------- 6 files changed, 133 deletions(-) delete mode 100644 kdb-bot/src/modules/boot_log/configuration/__init__.py delete mode 100644 kdb-bot/src/modules/boot_log/configuration/boot_log_server_settings.py delete mode 100644 kdb-bot/src/modules/boot_log/configuration/boot_log_settings.py delete mode 100644 kdb-bot/src/modules/permission/configuration/__init__.py delete mode 100644 kdb-bot/src/modules/permission/configuration/permission_server_settings.py delete mode 100644 kdb-bot/src/modules/permission/configuration/permission_settings.py 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 f7e050ef..00000000 --- a/kdb-bot/src/modules/boot_log/configuration/boot_log_server_settings.py +++ /dev/null @@ -1,17 +0,0 @@ -from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC - - -class BootLogServerSettings(ConfigurationModelABC): - def __init__(self, id: int = None, login_message_channel_id: int = None): - ConfigurationModelABC.__init__(self) - - self._id: int = 0 if id is None else id - self._login_message_channel_id: int = 0 if login_message_channel_id is None else login_message_channel_id - - @property - def id(self) -> int: - return self._id - - @property - def login_message_channel_id(self) -> int: - return self._login_message_channel_id 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 415d5899..00000000 --- a/kdb-bot/src/modules/boot_log/configuration/boot_log_settings.py +++ /dev/null @@ -1,21 +0,0 @@ -from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.utils.json_processor import JSONProcessor -from cpl_query.extension import List - -from modules.boot_log.configuration.boot_log_server_settings import ( - BootLogServerSettings, -) - - -class BootLogSettings(ConfigurationModelABC): - def __init__(self, **kwargs: dict): - ConfigurationModelABC.__init__(self) - - self._servers: List[BootLogServerSettings] = List() - for s in kwargs: - kwargs[s]["Id"] = s - self._servers.append(JSONProcessor.process(BootLogServerSettings, kwargs[s])) - - @property - def servers(self) -> List[BootLogServerSettings]: - return self._servers 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 6e928f36..00000000 --- a/kdb-bot/src/modules/permission/configuration/permission_server_settings.py +++ /dev/null @@ -1,22 +0,0 @@ -from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC - - -class PermissionServerSettings(ConfigurationModelABC): - def __init__(self, id: int = None, admin_role_ids: list = None, moderator_role_ids: list = None): - ConfigurationModelABC.__init__(self) - - self._id: int = 0 if id is None else id - self._admin_roles: list[int] = [] if admin_role_ids is None else admin_role_ids - self._moderator_roles: list[int] = [] if moderator_role_ids is None else moderator_role_ids - - @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 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 8ce4ad7b..00000000 --- a/kdb-bot/src/modules/permission/configuration/permission_settings.py +++ /dev/null @@ -1,21 +0,0 @@ -from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC -from cpl_core.utils.json_processor import JSONProcessor -from cpl_query.extension import List - -from modules.permission.configuration.permission_server_settings import ( - PermissionServerSettings, -) - - -class PermissionSettings(ConfigurationModelABC): - def __init__(self, **kwargs: dict): - ConfigurationModelABC.__init__(self) - - self._servers: List[PermissionServerSettings] = List() - for s in kwargs: - kwargs[s]["Id"] = s - self._servers.append(JSONProcessor.process(PermissionServerSettings, kwargs[s])) - - @property - def servers(self) -> List[PermissionServerSettings]: - return self._servers -- 2.45.2 From 05ddfb3de359efaff1ebb567d991de172b373005 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 7 Aug 2023 10:52:30 +0200 Subject: [PATCH 050/127] Added technician config queries #127 --- .../src/bot_data/model/technician_config.py | 4 ++ .../model/technician_config_history.py | 58 ++++++++++++++++ .../bot_data/model/technician_id_config.py | 4 ++ .../model/technician_id_config_history.py | 28 ++++++++ .../model/technician_ping_url_config.py | 4 ++ .../technician_ping_url_config_history.py | 28 ++++++++ kdb-bot/src/bot_graphql/graphql_module.py | 8 +++ .../bot_graphql/model/config_technician.gql | 62 +++++++++++++++++ kdb-bot/src/bot_graphql/model/query.gql | 2 + .../mutations/technician_config_mutation.py | 66 +++++++++++++++++++ .../technician_config_history_query.py | 11 ++++ .../queries/technician_config_query.py | 57 ++++++++++++++++ .../technician_id_config_history_query.py | 8 +++ ...echnician_ping_url_config_history_query.py | 8 +++ kdb-bot/src/bot_graphql/query.py | 3 + 15 files changed, 351 insertions(+) create mode 100644 kdb-bot/src/bot_data/model/technician_config_history.py create mode 100644 kdb-bot/src/bot_data/model/technician_id_config_history.py create mode 100644 kdb-bot/src/bot_data/model/technician_ping_url_config_history.py create mode 100644 kdb-bot/src/bot_graphql/model/config_technician.gql create mode 100644 kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py create mode 100644 kdb-bot/src/bot_graphql/queries/technician_config_history_query.py create mode 100644 kdb-bot/src/bot_graphql/queries/technician_config_query.py create mode 100644 kdb-bot/src/bot_graphql/queries/technician_id_config_history_query.py create mode 100644 kdb-bot/src/bot_graphql/queries/technician_ping_url_config_history_query.py diff --git a/kdb-bot/src/bot_data/model/technician_config.py b/kdb-bot/src/bot_data/model/technician_config.py index 062943d9..db43a82c 100644 --- a/kdb-bot/src/bot_data/model/technician_config.py +++ b/kdb-bot/src/bot_data/model/technician_config.py @@ -30,6 +30,10 @@ class TechnicianConfig(TableABC, ConfigurationModelABC): 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 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 index fcf0d83d..b89983e7 100644 --- a/kdb-bot/src/bot_data/model/technician_id_config.py +++ b/kdb-bot/src/bot_data/model/technician_id_config.py @@ -18,6 +18,10 @@ class TechnicianIdConfig(TableABC): 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 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 index 69d57965..59c4cfad 100644 --- a/kdb-bot/src/bot_data/model/technician_ping_url_config.py +++ b/kdb-bot/src/bot_data/model/technician_ping_url_config.py @@ -18,6 +18,10 @@ class TechnicianPingUrlConfig(TableABC): 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 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_graphql/graphql_module.py b/kdb-bot/src/bot_graphql/graphql_module.py index 480b4abc..8b3db926 100644 --- a/kdb-bot/src/bot_graphql/graphql_module.py +++ b/kdb-bot/src/bot_graphql/graphql_module.py @@ -42,6 +42,10 @@ from bot_graphql.queries.level_history_query import LevelHistoryQuery from bot_graphql.queries.level_query import LevelQuery 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 @@ -83,6 +87,10 @@ class GraphQLModule(ModuleABC): services.add_transient(QueryABC, LevelQuery) 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) diff --git a/kdb-bot/src/bot_graphql/model/config_technician.gql b/kdb-bot/src/bot_graphql/model/config_technician.gql new file mode 100644 index 00000000..d0c48ec7 --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/config_technician.gql @@ -0,0 +1,62 @@ +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 { + createTechnicianConfig(input: TechnicianConfigInput!): TechnicianConfig + updateTechnicianConfig(input: TechnicianConfigInput!): TechnicianConfig + deleteTechnicianConfig(id: ID): 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/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/mutations/technician_config_mutation.py b/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py new file mode 100644 index 00000000..7a7ed873 --- /dev/null +++ b/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py @@ -0,0 +1,66 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC + +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.user_role_enum import UserRoleEnum +from bot_graphql.abc.query_abc import QueryABC + + +class TechnicianConfigMutation(QueryABC): + def __init__( + self, + bot: DiscordBotServiceABC, + servers: ServerRepositoryABC, + technician_configs: TechnicianConfigRepositoryABC, + db: DatabaseContextABC, + ): + QueryABC.__init__(self, "TechnicianConfigMutation") + + self._bot = bot + self._servers = servers + self._technician_configs = technician_configs + self._db = db + + self.set_field("createTechnicianConfig", self.resolve_create_TechnicianConfig) + self.set_field("updateTechnicianConfig", self.resolve_update_TechnicianConfig) + self.set_field("deleteTechnicianConfig", self.resolve_delete_TechnicianConfig) + + def resolve_create_technician_config(self, *_, input: dict): + if self._technician_configs.does_technician_config_exists(): + return None + + technician_config = TechnicianConfig( + input["helpCommandReferenceUrl"], + input["waitForRestart"], + input["waitForShutdown"], + input["cacheMaxMessages"], + input["pingURLs"], + input["technicianIds"], + ) + self._technician_configs.add_technician_config(technician_config) + self._db.save_changes() + + return self._technician_configs.get_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.name = input["name"] if "name" in input else technician_config.name + + self._technician_configs.update_TechnicianConfig(technician_config) + self._db.save_changes() + + technician_config = self._technician_configs.get_TechnicianConfig_by_id(input["id"]) + return technician_config + + def resolve_delete_technician_config(self, *_, id: int): + technician_config = self._technician_configs.get_TechnicianConfig_by_id(id) + self._can_user_mutate_data(technician_config.server, UserRoleEnum.admin) + + self._technician_configs.delete_TechnicianConfig(technician_config) + self._db.save_changes() + + return technician_config 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..649dc510 --- /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()) -- 2.45.2 From f02acd7f944219a60dd7437c9402f1161f857804 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 7 Aug 2023 14:31:54 +0200 Subject: [PATCH 051/127] Added technician config mutation #127 --- kdb-bot/src/bot/config | 2 +- kdb-bot/src/bot_api/config | 2 +- .../bot_data/model/technician_id_config.py | 2 +- .../model/technician_ping_url_config.py | 2 +- kdb-bot/src/bot_graphql/graphql_module.py | 2 + kdb-bot/src/bot_graphql/model/mutation.gql | 1 + ...ig_technician.gql => technicianConfig.gql} | 2 - kdb-bot/src/bot_graphql/mutation.py | 3 + .../mutations/technician_config_mutation.py | 83 ++++++++++++------- 9 files changed, 63 insertions(+), 36 deletions(-) rename kdb-bot/src/bot_graphql/model/{config_technician.gql => technicianConfig.gql} (91%) diff --git a/kdb-bot/src/bot/config b/kdb-bot/src/bot/config index 4264ba15..359f9c38 160000 --- a/kdb-bot/src/bot/config +++ b/kdb-bot/src/bot/config @@ -1 +1 @@ -Subproject commit 4264ba15970a28f8a50c888bbf635a15c438bcf9 +Subproject commit 359f9c38c3ec825a89f3bf289a65ec035cfcb693 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_data/model/technician_id_config.py b/kdb-bot/src/bot_data/model/technician_id_config.py index b89983e7..6ba5f581 100644 --- a/kdb-bot/src/bot_data/model/technician_id_config.py +++ b/kdb-bot/src/bot_data/model/technician_id_config.py @@ -74,6 +74,6 @@ class TechnicianIdConfig(TableABC): return str( f""" DELETE FROM `CFG_TechnicianIds` - WHERE `Id` = {self._id}; + WHERE `TechnicianId` = {self._technician_id}; """ ) 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 index 59c4cfad..75d51c29 100644 --- a/kdb-bot/src/bot_data/model/technician_ping_url_config.py +++ b/kdb-bot/src/bot_data/model/technician_ping_url_config.py @@ -74,6 +74,6 @@ class TechnicianPingUrlConfig(TableABC): return str( f""" DELETE FROM `CFG_TechnicianPingUrls` - WHERE `Id` = {self._id}; + WHERE `URL` = {self._ping_url}; """ ) diff --git a/kdb-bot/src/bot_graphql/graphql_module.py b/kdb-bot/src/bot_graphql/graphql_module.py index 8b3db926..96c0720f 100644 --- a/kdb-bot/src/bot_graphql/graphql_module.py +++ b/kdb-bot/src/bot_graphql/graphql_module.py @@ -24,6 +24,7 @@ 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.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 @@ -120,5 +121,6 @@ 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(SeederService) diff --git a/kdb-bot/src/bot_graphql/model/mutation.gql b/kdb-bot/src/bot_graphql/model/mutation.gql index 0fb69b50..5f57cb8f 100644 --- a/kdb-bot/src/bot_graphql/model/mutation.gql +++ b/kdb-bot/src/bot_graphql/model/mutation.gql @@ -5,4 +5,5 @@ type Mutation { user: UserMutation userJoinedGameServer: UserJoinedGameServerMutation achievement: AchievementMutation + technicianConfig: TechnicianConfigMutation } \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/config_technician.gql b/kdb-bot/src/bot_graphql/model/technicianConfig.gql similarity index 91% rename from kdb-bot/src/bot_graphql/model/config_technician.gql rename to kdb-bot/src/bot_graphql/model/technicianConfig.gql index d0c48ec7..dc35704a 100644 --- a/kdb-bot/src/bot_graphql/model/config_technician.gql +++ b/kdb-bot/src/bot_graphql/model/technicianConfig.gql @@ -46,9 +46,7 @@ type TechnicianIdConfigHistory implements HistoryTableQuery { } type TechnicianConfigMutation { - createTechnicianConfig(input: TechnicianConfigInput!): TechnicianConfig updateTechnicianConfig(input: TechnicianConfigInput!): TechnicianConfig - deleteTechnicianConfig(id: ID): TechnicianConfig } input TechnicianConfigInput { diff --git a/kdb-bot/src/bot_graphql/mutation.py b/kdb-bot/src/bot_graphql/mutation.py index d8287d96..d5a62123 100644 --- a/kdb-bot/src/bot_graphql/mutation.py +++ b/kdb-bot/src/bot_graphql/mutation.py @@ -4,6 +4,7 @@ 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.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 +18,7 @@ class Mutation(MutationType): user_mutation: UserMutation, achievement_mutation: AchievementMutation, user_joined_game_server: UserJoinedGameServerMutation, + technician_config: TechnicianConfigMutation, ): MutationType.__init__(self) @@ -26,3 +28,4 @@ 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) diff --git a/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py b/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py index 7a7ed873..ed89ee48 100644 --- a/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py @@ -4,6 +4,8 @@ from cpl_discord.service import DiscordBotServiceABC 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 @@ -23,44 +25,65 @@ class TechnicianConfigMutation(QueryABC): self._technician_configs = technician_configs self._db = db - self.set_field("createTechnicianConfig", self.resolve_create_TechnicianConfig) - self.set_field("updateTechnicianConfig", self.resolve_update_TechnicianConfig) - self.set_field("deleteTechnicianConfig", self.resolve_delete_TechnicianConfig) - - def resolve_create_technician_config(self, *_, input: dict): - if self._technician_configs.does_technician_config_exists(): - return None - - technician_config = TechnicianConfig( - input["helpCommandReferenceUrl"], - input["waitForRestart"], - input["waitForShutdown"], - input["cacheMaxMessages"], - input["pingURLs"], - input["technicianIds"], - ) - self._technician_configs.add_technician_config(technician_config) - self._db.save_changes() - - return self._technician_configs.get_technician_config() + 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.name = input["name"] if "name" in input else technician_config.name + 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 = input["pingURLs"] if "pingURLs" in input else technician_config.ping_urls + technician_config.technician_ids = ( + 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._technician_configs.update_TechnicianConfig(technician_config) self._db.save_changes() - - technician_config = self._technician_configs.get_TechnicianConfig_by_id(input["id"]) return technician_config - def resolve_delete_technician_config(self, *_, id: int): - technician_config = self._technician_configs.get_TechnicianConfig_by_id(id) - self._can_user_mutate_data(technician_config.server, UserRoleEnum.admin) + 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_TechnicianConfig(technician_config) - self._db.save_changes() + self._technician_configs.delete_technician_ping_url_config(TechnicianPingUrlConfig(url)) - return technician_config + 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 url in old_config.technician_ids: + if url in new_config.technician_ids: + continue + + self._technician_configs.delete_technician_id_config(TechnicianIdConfig(url)) + + for url in new_config.technician_ids: + if url in old_config.technician_ids: + continue + + self._technician_configs.add_technician_id_config(TechnicianIdConfig(url)) -- 2.45.2 From eac367c61172206bf699a9d689f3684a6535151e Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 7 Aug 2023 14:59:19 +0200 Subject: [PATCH 052/127] Added technician config to frontend #127 --- kdb-web/package-lock.json | 10 +- kdb-web/package.json | 2 +- .../models/config/technician-config.model.ts | 11 + .../src/app/models/graphql/mutations.model.ts | 26 ++ .../src/app/models/graphql/queries.model.ts | 17 ++ kdb-web/src/app/models/graphql/query.model.ts | 5 + .../src/app/models/graphql/result.model.ts | 7 + .../settings/settings.component.html | 267 ++++++++++-------- .../components/settings/settings.component.ts | 141 ++++++--- .../src/app/modules/shared/shared.module.ts | 6 +- kdb-web/src/assets/config.json | 4 +- kdb-web/src/styles.scss | 9 + 12 files changed, 349 insertions(+), 156 deletions(-) create mode 100644 kdb-web/src/app/models/config/technician-config.model.ts 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/package.json b/kdb-web/package.json index d6381d85..e9e0874b 100644 --- a/kdb-web/package.json +++ b/kdb-web/package.json @@ -51,4 +51,4 @@ "tslib": "^2.4.1", "typescript": "~4.9.5" } -} \ No newline at end of file +} 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..02ade32c --- /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..2aa447cd 100644 --- a/kdb-web/src/app/models/graphql/mutations.model.ts +++ b/kdb-web/src/app/models/graphql/mutations.model.ts @@ -165,4 +165,30 @@ 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 + } + } + } + `; } diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts index 6dc78904..5311141e 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -1,5 +1,22 @@ export class Queries { + static technicianConfigQuery = ` + query technicianConfigQuery { + technicianConfig { + id + helpCommandReferenceUrl + waitForRestart + waitForShutdown + cacheMaxMessages + pingURLs + technicianIds + + createdAt + modifiedAt + } + } + `; + static guildsQuery = ` query GuildsQuery($id: ID) { guilds(filter: {id: $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..1cc35083 100644 --- a/kdb-web/src/app/models/graphql/query.model.ts +++ b/kdb-web/src/app/models/graphql/query.model.ts @@ -4,12 +4,17 @@ 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"; export interface Query { serverCount: number; servers: Server[]; } +export interface TechnicianConfigQuery { + technicianConfig: TechnicianConfig; +} + 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..37445578 100644 --- a/kdb-web/src/app/models/graphql/result.model.ts +++ b/kdb-web/src/app/models/graphql/result.model.ts @@ -3,6 +3,7 @@ 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"; export interface GraphQLResult { data: { @@ -47,6 +48,12 @@ export interface LevelMutationResult { }; } +export interface TechnicianConfigMutationResult { + technicianConfig: { + updateTechnicianConfig?: TechnicianConfig + }; +} + 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..a710fa79 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,168 @@

- {{'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..d6030c26 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 @@ -1,5 +1,5 @@ import { Component, OnInit } from "@angular/core"; -import { FormBuilder, FormGroup, Validators } from "@angular/forms"; +import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from "@angular/forms"; import { TranslateService } from "@ngx-translate/core"; import { catchError } from "rxjs/operators"; import { SettingsDTO } from "src/app/models/config/settings.dto"; @@ -9,66 +9,111 @@ 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 { LevelMutationResult, TechnicianConfigMutationResult } from "../../../../../models/graphql/result.model"; +import { Mutations } from "../../../../../models/graphql/mutations.model"; +import { AuthService } from "../../../../../services/auth/auth.service"; +import { ConfirmationDialogService } from "../../../../../services/confirmation-dialog/confirmation-dialog.service"; +import { SidebarService } from "../../../../../services/sidebar/sidebar.service"; +import { ActivatedRoute } from "@angular/router"; @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; + technicianConfigForm: FormGroup = this.formBuilder.group({ + helpCommandReferenceUrl: [null, [Validators.required]], + waitForRestart: [null, [Validators.required]], + waitForShutdown: [null, [Validators.required]], + cacheMaxMessages: [null, [Validators.required]], + pingUrls: this.formBuilder.array([]) + }); 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]] }); + this.technicianConfigForm = this.formBuilder.group({ + helpCommandReferenceUrl: [this.config.helpCommandReferenceUrl, [Validators.required]], + waitForRestart: [this.config.waitForRestart, [Validators.required]], + waitForShutdown: [this.config.waitForShutdown, [Validators.required]], + cacheMaxMessages: [this.config.cacheMaxMessages, [Validators.required]], + pingUrls: this.formBuilder.array([]) + }); + const pingUrls = this.technicianConfigForm.controls["pingUrls"]; + for (const url of this.config.pingURLs ?? []) { + pingUrls.push(new FormControl(url, [Validators.required])); + } } testMail(): void { @@ -82,27 +127,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 +158,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(); + this.toastService.error(this.translate.instant("admin.settings.message.technician_config_create_failed"), this.translate.instant("admin.settings.message.technician_config_create_failed_d")); + 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/shared.module.ts b/kdb-web/src/app/modules/shared/shared.module.ts index e2d14884..61a5db6c 100644 --- a/kdb-web/src/app/modules/shared/shared.module.ts +++ b/kdb-web/src/app/modules/shared/shared.module.ts @@ -24,6 +24,7 @@ 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'; @NgModule({ @@ -56,6 +57,7 @@ import { HistoryBtnComponent } from './components/history-btn/history-btn.compon InputNumberModule, ImageModule, SidebarModule, + DataViewModule, ], exports: [ ButtonModule, @@ -82,7 +84,9 @@ import { HistoryBtnComponent } from './components/history-btn/history-btn.compon InputNumberModule, ImageModule, SidebarModule, - HistoryBtnComponent + HistoryBtnComponent, + DataViewModule, + DataViewLayoutOptions ] }) export class SharedModule { } diff --git a/kdb-web/src/assets/config.json b/kdb-web/src/assets/config.json index a2d9a6c2..9d35b928 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": [ { @@ -25,4 +25,4 @@ "Name": "sh-edraft-dark-theme" } ] -} \ No newline at end of file +} 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; } -- 2.45.2 From 8922524f44276085212907bf6fb8026a800d7a77 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 14 Aug 2023 11:58:36 +0200 Subject: [PATCH 053/127] Added logic to edit technician config in WI #127 --- .../service/data_integrity_service.py | 2 +- .../model/technician_ping_url_config.py | 2 +- .../mutations/technician_config_mutation.py | 29 +++- kdb-web/package.json | 2 +- .../settings/settings.component.html | 94 ++++++++++++ .../components/settings/settings.component.ts | 142 ++++++++++++++---- kdb-web/src/assets/config.json | 2 +- 7 files changed, 234 insertions(+), 39 deletions(-) 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 78b64e73..923cf4cb 100644 --- a/kdb-bot/src/bot_core/service/data_integrity_service.py +++ b/kdb-bot/src/bot_core/service/data_integrity_service.py @@ -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}") 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 index 75d51c29..31983624 100644 --- a/kdb-bot/src/bot_data/model/technician_ping_url_config.py +++ b/kdb-bot/src/bot_data/model/technician_ping_url_config.py @@ -74,6 +74,6 @@ class TechnicianPingUrlConfig(TableABC): return str( f""" DELETE FROM `CFG_TechnicianPingUrls` - WHERE `URL` = {self._ping_url}; + WHERE `URL` = '{self._ping_url}'; """ ) diff --git a/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py b/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py index ed89ee48..da3b7651 100644 --- a/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py @@ -1,6 +1,8 @@ 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 @@ -13,6 +15,7 @@ from bot_graphql.abc.query_abc import QueryABC class TechnicianConfigMutation(QueryABC): def __init__( self, + logger: ApiLogger, bot: DiscordBotServiceABC, servers: ServerRepositoryABC, technician_configs: TechnicianConfigRepositoryABC, @@ -20,6 +23,7 @@ class TechnicianConfigMutation(QueryABC): ): QueryABC.__init__(self, "TechnicianConfigMutation") + self._logger = logger self._bot = bot self._servers = servers self._technician_configs = technician_configs @@ -45,9 +49,13 @@ class TechnicianConfigMutation(QueryABC): technician_config.cache_max_messages = ( input["cacheMaxMessages"] if "cacheMaxMessages" in input else technician_config.cache_max_messages ) - technician_config.ping_urls = input["pingURLs"] if "pingURLs" in input else technician_config.ping_urls + technician_config.ping_urls = ( + List(str, input["pingURLs"]) if "pingURLs" in input else technician_config.ping_urls + ) technician_config.technician_ids = ( - input["technicianIds"] if "technicianIds" in input else 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) @@ -76,14 +84,19 @@ class TechnicianConfigMutation(QueryABC): def _update_technician_ids(self, new_config: TechnicianConfig): old_config = self._technician_configs.get_technician_config() - for url in old_config.technician_ids: - if url in new_config.technician_ids: + 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(url)) + self._technician_configs.delete_technician_id_config(TechnicianIdConfig(technician_id)) - for url in new_config.technician_ids: - if url in old_config.technician_ids: + 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(url)) + self._technician_configs.add_technician_id_config(TechnicianIdConfig(technician_id)) diff --git a/kdb-web/package.json b/kdb-web/package.json index e9e0874b..d6381d85 100644 --- a/kdb-web/package.json +++ b/kdb-web/package.json @@ -51,4 +51,4 @@ "tslib": "^2.4.1", "typescript": "~4.9.5" } -} +} \ No newline at end of file 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 a710fa79..76707043 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 @@ -160,6 +160,100 @@
+ +
+
+
+
+ {{'admin.settings.bot.ping_urls' | translate}}: +
+
+ + +
+
+ +
+
+
+ + + + + + + + + {{pingUrl.value}} + + + + +
+ + + + + +
+ + +
+
+
+
+
+
+ +
+
+
+ {{'admin.settings.bot.technicianIds' | translate}}: +
+
+ + +
+
+ +
+
+
+ + + + + + + + + {{technicianId.value}} + + + + +
+ + + + + +
+ + +
+
+
+
+
+
+
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 d6030c26..c0cb39b8 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 @@ -14,12 +14,20 @@ import { TechnicianConfig } from "../../../../../models/config/technician-config import { TechnicianConfigQuery } from "../../../../../models/graphql/query.model"; import { Queries } from "../../../../../models/graphql/queries.model"; import { DataService } from "../../../../../services/data/data.service"; -import { LevelMutationResult, TechnicianConfigMutationResult } from "../../../../../models/graphql/result.model"; +import { TechnicianConfigMutationResult } from "../../../../../models/graphql/result.model"; import { Mutations } from "../../../../../models/graphql/mutations.model"; import { AuthService } from "../../../../../services/auth/auth.service"; -import { ConfirmationDialogService } from "../../../../../services/confirmation-dialog/confirmation-dialog.service"; -import { SidebarService } from "../../../../../services/sidebar/sidebar.service"; -import { ActivatedRoute } from "@angular/router"; +import { Table } from "primeng/table"; + +type PingUrl = { + id: number; + value: string; +}; + +type TechnicianId = { + id: number; + value: string; +}; @Component({ selector: "app-settings", @@ -33,9 +41,12 @@ export class SettingsComponent implements OnInit { helpCommandReferenceUrl: [null, [Validators.required]], waitForRestart: [null, [Validators.required]], waitForShutdown: [null, [Validators.required]], - cacheMaxMessages: [null, [Validators.required]], - pingUrls: this.formBuilder.array([]) + cacheMaxMessages: [null, [Validators.required]] }); + pingUrls: PingUrl[] = []; + clonedPingUrls: { [s: number]: PingUrl } = {}; + technicianIds: TechnicianId[] = []; + clonedTechnicianIds: { [s: number]: TechnicianId } = {}; data: SettingsDTO = { webVersion: "", apiVersion: "", @@ -71,7 +82,7 @@ export class SettingsComponent implements OnInit { private toastService: ToastService, private translate: TranslateService, private authService: AuthService, - private spinner: SpinnerService, + private spinner: SpinnerService ) { } @@ -107,12 +118,18 @@ export class SettingsComponent implements OnInit { helpCommandReferenceUrl: [this.config.helpCommandReferenceUrl, [Validators.required]], waitForRestart: [this.config.waitForRestart, [Validators.required]], waitForShutdown: [this.config.waitForShutdown, [Validators.required]], - cacheMaxMessages: [this.config.cacheMaxMessages, [Validators.required]], - pingUrls: this.formBuilder.array([]) + cacheMaxMessages: [this.config.cacheMaxMessages, [Validators.required]] }); - const pingUrls = this.technicianConfigForm.controls["pingUrls"]; + let id = 0; for (const url of this.config.pingURLs ?? []) { - pingUrls.push(new FormControl(url, [Validators.required])); + this.pingUrls.push({ id: id, value: url }); + id++; + } + + id = 0; + for (const technicianId of this.config.technicianIds ?? []) { + this.technicianIds.push({ id: id, value: technicianId }); + id++; } } @@ -165,22 +182,93 @@ export class SettingsComponent implements OnInit { 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(); - this.toastService.error(this.translate.instant("admin.settings.message.technician_config_create_failed"), this.translate.instant("admin.settings.message.technician_config_create_failed_d")); - 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")); - }); + this.dataService.mutation(Mutations.updateTechnicianConfig, { + helpCommandReferenceUrl: this.config.helpCommandReferenceUrl, + waitForRestart: this.config.waitForRestart, + waitForShutdown: this.config.waitForShutdown, + cacheMaxMessages: this.config.cacheMaxMessages, + pingURLs: this.pingUrls.filter(value => value.value).map(value => { + return value.value; + }), + technicianIds: this.technicianIds.filter(value => value.value).map(value => { + return value.value; + }) + } + ).pipe(catchError(err => { + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("admin.settings.message.technician_config_create_failed"), this.translate.instant("admin.settings.message.technician_config_create_failed_d")); + 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")); + }); + } + + pingUrlsAddNew(table: Table) { + const id = Math.max.apply(Math, this.pingUrls.map(url => { + return url.id ?? 0; + })) + 1; + const newItem = { id: id, value: "" }; + this.pingUrls.push(newItem); + + table.initRowEdit(newItem); + const index = this.pingUrls.findIndex(l => l.id == newItem.id); + this.pingUrlsEditInit(newItem, index); + } + + pingUrlsEditInit(url: PingUrl, index: number) { + this.clonedPingUrls[index] = { ...url }; + } + + pingUrlsDelete(index: number) { + this.pingUrls.splice(index, 1); + } + + pingUrlsEditSave(url: PingUrl, index: number) { + if (!url.value || this.pingUrls[index] == this.clonedPingUrls[index]) { + return; + } + + delete this.clonedPingUrls[index]; + } + + pingUrlsEditCancel(url: PingUrl, index: number) { + this.pingUrls[index] = this.clonedPingUrls[index]; + delete this.clonedPingUrls[index]; + } + + + technicianIdsAddNew(table: Table) { + const id = Math.max.apply(Math, this.technicianIds.map(url => { + return url.id ?? 0; + })) + 1; + const newItem = { id: id, value: "" }; + this.technicianIds.push(newItem); + + table.initRowEdit(newItem); + const index = this.technicianIds.findIndex(l => l.id == newItem.id); + this.technicianIdsEditInit(newItem, index); + } + + technicianIdsEditInit(url: PingUrl, index: number) { + this.clonedTechnicianIds[index] = { ...url }; + } + + technicianIdsDelete(index: number) { + this.technicianIds.splice(index, 1); + } + + technicianIdsEditSave(url: PingUrl, index: number) { + if (!url.value || this.technicianIds[index] == this.clonedTechnicianIds[index]) { + return; + } + + delete this.clonedTechnicianIds[index]; + } + + technicianIdsEditCancel(url: PingUrl, index: number) { + this.technicianIds[index] = this.clonedTechnicianIds[index]; + delete this.clonedTechnicianIds[index]; } } diff --git a/kdb-web/src/assets/config.json b/kdb-web/src/assets/config.json index 9d35b928..581bbcb8 100644 --- a/kdb-web/src/assets/config.json +++ b/kdb-web/src/assets/config.json @@ -25,4 +25,4 @@ "Name": "sh-edraft-dark-theme" } ] -} +} \ No newline at end of file -- 2.45.2 From 4c42949516019188c4386e685ffe7915b2c078d7 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 14 Aug 2023 12:13:45 +0200 Subject: [PATCH 054/127] Added translations #127 --- kdb-web/src/assets/i18n/de.json | 26 ++++++++++++++++++++------ kdb-web/src/assets/i18n/en.json | 25 ++++++++++++++++++++----- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index 7deee1ea..e499fedf 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", + "technicianIds": "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", @@ -144,13 +158,12 @@ "messageId": "Nachricht Id", "minXp": "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" }, diff --git a/kdb-web/src/assets/i18n/en.json b/kdb-web/src/assets/i18n/en.json index b4e584ad..3d709daa 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", + "technicianIds": "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", @@ -144,13 +158,12 @@ "messageId": "Message Id", "minXp": "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" -- 2.45.2 From 5d36f1188a43ae3252f19a17808da197a8627bf1 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 14 Aug 2023 15:53:42 +0200 Subject: [PATCH 055/127] Added server config mutation #127 --- .../abc/server_config_repository_abc.py | 6 +- .../model/server_afk_channel_ids_config.py | 15 +- kdb-bot/src/bot_data/model/server_config.py | 73 ++++++++ .../bot_data/model/server_config_history.py | 102 ++++++++++++ .../model/server_team_role_ids_config.py | 15 +- .../server_config_repository_service.py | 27 +-- kdb-bot/src/bot_graphql/graphql_module.py | 4 + kdb-bot/src/bot_graphql/model/mutation.gql | 1 + kdb-bot/src/bot_graphql/model/server.gql | 2 + .../src/bot_graphql/model/serverConfig.gql | 94 +++++++++++ kdb-bot/src/bot_graphql/mutation.py | 3 + .../mutations/server_config_mutation.py | 157 ++++++++++++++++++ .../queries/server_config_query.py | 39 +++++ .../src/bot_graphql/queries/server_query.py | 3 + .../queries/technician_config_query.py | 20 +-- .../config/events/config_on_ready_event.py | 2 +- 16 files changed, 537 insertions(+), 26 deletions(-) create mode 100644 kdb-bot/src/bot_data/model/server_config_history.py create mode 100644 kdb-bot/src/bot_graphql/model/serverConfig.gql create mode 100644 kdb-bot/src/bot_graphql/mutations/server_config_mutation.py create mode 100644 kdb-bot/src/bot_graphql/queries/server_config_query.py 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 index e6fd480c..f66fdc89 100644 --- a/kdb-bot/src/bot_data/abc/server_config_repository_abc.py +++ b/kdb-bot/src/bot_data/abc/server_config_repository_abc.py @@ -15,7 +15,11 @@ class ServerConfigRepositoryABC(ABC): pass @abstractmethod - def get_server_config(self, server_id: int) -> ServerConfig: + 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 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 index f567ccee..9b182426 100644 --- 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 @@ -41,12 +41,21 @@ class ServerAFKChannelIdsConfig(TableABC): """ ) + @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` ( - `RoleId`, + `ChannelId`, `ServerId` ) VALUES ( {self._channel_id}, @@ -60,7 +69,7 @@ class ServerAFKChannelIdsConfig(TableABC): return str( f""" UPDATE `CFG_ServerAFKChannelIds` - SET `RoleId` = {self._channel_id}, + SET `ChannelId` = {self._channel_id}, `ServerId` = {self._server_id} WHERE `Id` = {self._id}; """ @@ -71,6 +80,6 @@ class ServerAFKChannelIdsConfig(TableABC): return str( f""" DELETE FROM `CFG_ServerAFKChannelIds` - WHERE `Id` = {self._id}; + 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 index b962e221..ba1db9f6 100644 --- a/kdb-bot/src/bot_data/model/server_config.py +++ b/kdb-bot/src/bot_data/model/server_config.py @@ -53,66 +53,130 @@ class ServerConfig(TableABC, ConfigurationModelABC): 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 @@ -134,6 +198,15 @@ class ServerConfig(TableABC, ConfigurationModelABC): """ ) + @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( 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 index aee799fd..dfd870dd 100644 --- 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 @@ -24,6 +24,10 @@ class ServerTeamRoleIdsConfig(TableABC): 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 @@ -49,6 +53,15 @@ class ServerTeamRoleIdsConfig(TableABC): """ ) + @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( @@ -82,6 +95,6 @@ class ServerTeamRoleIdsConfig(TableABC): return str( f""" DELETE FROM `CFG_ServerTeamRoleIds` - WHERE `Id` = {self._id}; + WHERE `RoleId` = {self._role_id}; """ ) 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 index 3b069e71..09c1bff5 100644 --- a/kdb-bot/src/bot_data/service/server_config_repository_service.py +++ b/kdb-bot/src/bot_data/service/server_config_repository_service.py @@ -18,12 +18,12 @@ class ServerConfigRepositoryService(ServerConfigRepositoryABC): self._context = db_context self._servers = servers - def _get_team_role_ids(self, server_team_role_id: int) -> List[ServerTeamRoleIdsConfig]: + 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_id_string(server_team_role_id)}" + __name__, f"Send SQL command: {ServerTeamRoleIdsConfig.get_select_by_server_id_string(server_id)}" ) - results = self._context.select(ServerTeamRoleIdsConfig.get_select_by_id_string(server_team_role_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( @@ -34,12 +34,13 @@ class ServerConfigRepositoryService(ServerConfigRepositoryABC): return ids - def _get_afk_channel_ids(self, server_team_role_id: int) -> List[int]: - urls = List(str) + 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_id_string(server_team_role_id)}" + __name__, + f"Send SQL command: {ServerAFKChannelIdsConfig.get_select_by_server_id_string(server_id)}", ) - results = self._context.select(ServerAFKChannelIdsConfig.get_select_by_id_string(server_team_role_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]) @@ -62,8 +63,8 @@ class ServerConfigRepositoryService(ServerConfigRepositoryABC): result[12], result[13], self._servers.get_server_by_id(result[14]), - self._get_afk_channel_ids(result[0]), - self._get_team_role_ids(result[0]), + self._get_afk_channel_ids(result[14]), + self._get_team_role_ids(result[14]), result[15], result[16], id=result[0], @@ -75,12 +76,18 @@ class ServerConfigRepositoryService(ServerConfigRepositoryABC): return len(result) > 0 - def get_server_config(self, server_id: int) -> ServerConfig: + 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) diff --git a/kdb-bot/src/bot_graphql/graphql_module.py b/kdb-bot/src/bot_graphql/graphql_module.py index 96c0720f..2b294950 100644 --- a/kdb-bot/src/bot_graphql/graphql_module.py +++ b/kdb-bot/src/bot_graphql/graphql_module.py @@ -24,6 +24,7 @@ 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 @@ -41,6 +42,7 @@ 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 @@ -86,6 +88,7 @@ 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) @@ -122,5 +125,6 @@ class GraphQLModule(ModuleABC): 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 5f57cb8f..aa1d8cd6 100644 --- a/kdb-bot/src/bot_graphql/model/mutation.gql +++ b/kdb-bot/src/bot_graphql/model/mutation.gql @@ -6,4 +6,5 @@ type Mutation { userJoinedGameServer: UserJoinedGameServerMutation achievement: AchievementMutation technicianConfig: TechnicianConfigMutation + serverConfig: ServerConfigMutation } \ 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/mutation.py b/kdb-bot/src/bot_graphql/mutation.py index d5a62123..4631e321 100644 --- a/kdb-bot/src/bot_graphql/mutation.py +++ b/kdb-bot/src/bot_graphql/mutation.py @@ -4,6 +4,7 @@ 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 @@ -19,6 +20,7 @@ class Mutation(MutationType): achievement_mutation: AchievementMutation, user_joined_game_server: UserJoinedGameServerMutation, technician_config: TechnicianConfigMutation, + server_config: ServerConfigMutation, ): MutationType.__init__(self) @@ -29,3 +31,4 @@ class Mutation(MutationType): 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..22669a7c --- /dev/null +++ b/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py @@ -0,0 +1,157 @@ +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: + 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/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_query.py b/kdb-bot/src/bot_graphql/queries/technician_config_query.py index 649dc510..3cda423f 100644 --- a/kdb-bot/src/bot_graphql/queries/technician_config_query.py +++ b/kdb-bot/src/bot_graphql/queries/technician_config_query.py @@ -27,11 +27,11 @@ class TechnicianConfigQuery(DataQueryWithHistoryABC): results = self._db.select( f""" - SELECT * - FROM CFG_TechnicianPingUrlsHistory - WHERE Id = {entry.id} - ORDER BY DateTo DESC; - """ + SELECT * + FROM CFG_TechnicianPingUrlsHistory + WHERE Id = {entry.id} + ORDER BY DateTo DESC; + """ ) for result in results: @@ -44,11 +44,11 @@ class TechnicianConfigQuery(DataQueryWithHistoryABC): results = self._db.select( f""" - SELECT * - FROM CFG_TechnicianIdsHistory - WHERE Id = {entry.id} - ORDER BY DateTo DESC; - """ + SELECT * + FROM CFG_TechnicianIdsHistory + WHERE Id = {entry.id} + ORDER BY DateTo DESC; + """ ) for result in results: 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 index 614620c8..f9bf3012 100644 --- a/kdb-bot/src/modules/config/events/config_on_ready_event.py +++ b/kdb-bot/src/modules/config/events/config_on_ready_event.py @@ -29,7 +29,7 @@ class ConfigOnReadyEvent(OnReadyABC): 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(server.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 ) -- 2.45.2 From 6c39cd1ae121f3c2a9f3fa19d6d9b02ee018e694 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 14 Aug 2023 18:06:32 +0200 Subject: [PATCH 056/127] Added server config to frontend #127 --- .../mutations/server_config_mutation.py | 6 + .../app/models/config/server-config.model.ts | 21 +++ .../models/config/technician-config.model.ts | 4 +- .../src/app/models/graphql/mutations.model.ts | 68 +++++++++- .../src/app/models/graphql/queries.model.ts | 67 +++++++--- kdb-web/src/app/models/graphql/query.model.ts | 5 + .../src/app/models/graphql/result.model.ts | 7 + .../settings/settings.component.html | 96 +------------- .../components/settings/settings.component.ts | 114 +--------------- .../config-list/config-list.component.html | 45 +++++++ .../config-list/config-list.component.scss | 0 .../config-list/config-list.component.spec.ts | 23 ++++ .../config-list/config-list.component.ts | 72 ++++++++++ .../src/app/modules/shared/shared.module.ts | 61 ++++----- .../achievement/achievement.component.ts | 3 - .../auto-roles-rules.component.ts | 3 - .../auto-roles/auto-roles.component.ts | 2 - .../components/config/config.component.html | 123 ++++++++++++++++++ .../components/config/config.component.scss | 0 .../config/config.component.spec.ts | 23 ++++ .../components/config/config.component.ts | 116 +++++++++++++++++ .../server/config/config-routing.module.ts | 13 ++ .../view/server/config/config.module.ts | 19 +++ .../components/levels/levels.component.ts | 3 - .../view/server/members/members.component.ts | 1 - .../view/server/server-routing.module.ts | 3 +- kdb-web/src/app/services/data/data.service.ts | 10 +- .../app/services/sidebar/sidebar.service.ts | 13 +- kdb-web/src/assets/i18n/de.json | 26 +++- kdb-web/src/assets/i18n/en.json | 28 +++- 30 files changed, 699 insertions(+), 276 deletions(-) create mode 100644 kdb-web/src/app/models/config/server-config.model.ts create mode 100644 kdb-web/src/app/modules/shared/components/config-list/config-list.component.html create mode 100644 kdb-web/src/app/modules/shared/components/config-list/config-list.component.scss create mode 100644 kdb-web/src/app/modules/shared/components/config-list/config-list.component.spec.ts create mode 100644 kdb-web/src/app/modules/shared/components/config-list/config-list.component.ts create mode 100644 kdb-web/src/app/modules/view/server/config/components/config/config.component.html create mode 100644 kdb-web/src/app/modules/view/server/config/components/config/config.component.scss create mode 100644 kdb-web/src/app/modules/view/server/config/components/config/config.component.spec.ts create mode 100644 kdb-web/src/app/modules/view/server/config/components/config/config.component.ts create mode 100644 kdb-web/src/app/modules/view/server/config/config-routing.module.ts create mode 100644 kdb-web/src/app/modules/view/server/config/config.module.ts diff --git a/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py b/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py index 22669a7c..2480be82 100644 --- a/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py @@ -150,6 +150,12 @@ class ServerConfigMutation(QueryABC): 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 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 index 02ade32c..6e1430f0 100644 --- a/kdb-web/src/app/models/config/technician-config.model.ts +++ b/kdb-web/src/app/models/config/technician-config.model.ts @@ -6,6 +6,6 @@ export interface TechnicianConfig extends DataWithHistory { waitForRestart?: number; waitForShutdown?: number; cacheMaxMessages?: number; - pingURLs?: string[]; - technicianIds?: string[]; + 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 2aa447cd..7905eff4 100644 --- a/kdb-web/src/app/models/graphql/mutations.model.ts +++ b/kdb-web/src/app/models/graphql/mutations.model.ts @@ -166,8 +166,6 @@ export class Mutations { } `; - - static updateTechnicianConfig = ` mutation updateTechnicianConfig($id: ID, $helpCommandReferenceUrl: String, $waitForRestart: Int, $waitForShutdown: Int, $cacheMaxMessages: Int, $pingURLs: [String], $technicianIds: [String]) { technicianConfig { @@ -191,4 +189,70 @@ export class Mutations { } } `; + + 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 5311141e..55998599 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -1,22 +1,5 @@ export class Queries { - static technicianConfigQuery = ` - query technicianConfigQuery { - technicianConfig { - id - helpCommandReferenceUrl - waitForRestart - waitForShutdown - cacheMaxMessages - pingURLs - technicianIds - - createdAt - modifiedAt - } - } - `; - static guildsQuery = ` query GuildsQuery($id: ID) { guilds(filter: {id: $id}) { @@ -71,7 +54,7 @@ export class Queries { } } } - ` + `; static levelQuery = ` query LevelsList($serverId: ID, $filter: LevelFilter, $page: Page, $sort: Sort) { @@ -361,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 1cc35083..42eeb69d 100644 --- a/kdb-web/src/app/models/graphql/query.model.ts +++ b/kdb-web/src/app/models/graphql/query.model.ts @@ -5,6 +5,7 @@ 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; @@ -15,6 +16,10 @@ 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 37445578..573f98ce 100644 --- a/kdb-web/src/app/models/graphql/result.model.ts +++ b/kdb-web/src/app/models/graphql/result.model.ts @@ -4,6 +4,7 @@ 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: { @@ -54,6 +55,12 @@ export interface TechnicianConfigMutationResult { }; } +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 76707043..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 @@ -160,103 +160,13 @@
- -
-
-
-
- {{'admin.settings.bot.ping_urls' | translate}}: -
-
- - -
-
- -
-
-
- - - - - - - - - {{pingUrl.value}} - - - - -
- - - - - -
- - -
-
-
-
-
-
- -
-
-
- {{'admin.settings.bot.technicianIds' | translate}}: -
-
- - -
-
- -
-
-
- - - - - - - - - {{technicianId.value}} - - - - -
- - - - - -
- - -
-
-
-
-
+ +
+ (click)="saveTechnicianConfig()">
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 c0cb39b8..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 @@ -1,5 +1,5 @@ import { Component, OnInit } from "@angular/core"; -import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from "@angular/forms"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; import { TranslateService } from "@ngx-translate/core"; import { catchError } from "rxjs/operators"; import { SettingsDTO } from "src/app/models/config/settings.dto"; @@ -17,17 +17,7 @@ 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"; -import { Table } from "primeng/table"; -type PingUrl = { - id: number; - value: string; -}; - -type TechnicianId = { - id: number; - value: string; -}; @Component({ selector: "app-settings", @@ -37,16 +27,6 @@ type TechnicianId = { export class SettingsComponent implements OnInit { testMailForm!: FormGroup; - technicianConfigForm: FormGroup = this.formBuilder.group({ - helpCommandReferenceUrl: [null, [Validators.required]], - waitForRestart: [null, [Validators.required]], - waitForShutdown: [null, [Validators.required]], - cacheMaxMessages: [null, [Validators.required]] - }); - pingUrls: PingUrl[] = []; - clonedPingUrls: { [s: number]: PingUrl } = {}; - technicianIds: TechnicianId[] = []; - clonedTechnicianIds: { [s: number]: TechnicianId } = {}; data: SettingsDTO = { webVersion: "", apiVersion: "", @@ -114,23 +94,6 @@ export class SettingsComponent implements OnInit { this.testMailForm = this.formBuilder.group({ mail: [null, [Validators.required, Validators.email]] }); - this.technicianConfigForm = this.formBuilder.group({ - helpCommandReferenceUrl: [this.config.helpCommandReferenceUrl, [Validators.required]], - waitForRestart: [this.config.waitForRestart, [Validators.required]], - waitForShutdown: [this.config.waitForShutdown, [Validators.required]], - cacheMaxMessages: [this.config.cacheMaxMessages, [Validators.required]] - }); - let id = 0; - for (const url of this.config.pingURLs ?? []) { - this.pingUrls.push({ id: id, value: url }); - id++; - } - - id = 0; - for (const technicianId of this.config.technicianIds ?? []) { - this.technicianIds.push({ id: id, value: technicianId }); - id++; - } } testMail(): void { @@ -187,16 +150,11 @@ export class SettingsComponent implements OnInit { waitForRestart: this.config.waitForRestart, waitForShutdown: this.config.waitForShutdown, cacheMaxMessages: this.config.cacheMaxMessages, - pingURLs: this.pingUrls.filter(value => value.value).map(value => { - return value.value; - }), - technicianIds: this.technicianIds.filter(value => value.value).map(value => { - return value.value; - }) + pingURLs: this.config.pingURLs, + technicianIds: this.config.technicianIds } ).pipe(catchError(err => { this.spinner.hideSpinner(); - this.toastService.error(this.translate.instant("admin.settings.message.technician_config_create_failed"), this.translate.instant("admin.settings.message.technician_config_create_failed_d")); return throwError(err); })).subscribe(result => { this.spinner.hideSpinner(); @@ -204,71 +162,5 @@ export class SettingsComponent implements OnInit { }); } - pingUrlsAddNew(table: Table) { - const id = Math.max.apply(Math, this.pingUrls.map(url => { - return url.id ?? 0; - })) + 1; - const newItem = { id: id, value: "" }; - this.pingUrls.push(newItem); - - table.initRowEdit(newItem); - const index = this.pingUrls.findIndex(l => l.id == newItem.id); - this.pingUrlsEditInit(newItem, index); - } - - pingUrlsEditInit(url: PingUrl, index: number) { - this.clonedPingUrls[index] = { ...url }; - } - - pingUrlsDelete(index: number) { - this.pingUrls.splice(index, 1); - } - - pingUrlsEditSave(url: PingUrl, index: number) { - if (!url.value || this.pingUrls[index] == this.clonedPingUrls[index]) { - return; - } - - delete this.clonedPingUrls[index]; - } - - pingUrlsEditCancel(url: PingUrl, index: number) { - this.pingUrls[index] = this.clonedPingUrls[index]; - delete this.clonedPingUrls[index]; - } - - - technicianIdsAddNew(table: Table) { - const id = Math.max.apply(Math, this.technicianIds.map(url => { - return url.id ?? 0; - })) + 1; - const newItem = { id: id, value: "" }; - this.technicianIds.push(newItem); - - table.initRowEdit(newItem); - const index = this.technicianIds.findIndex(l => l.id == newItem.id); - this.technicianIdsEditInit(newItem, index); - } - - technicianIdsEditInit(url: PingUrl, index: number) { - this.clonedTechnicianIds[index] = { ...url }; - } - - technicianIdsDelete(index: number) { - this.technicianIds.splice(index, 1); - } - - technicianIdsEditSave(url: PingUrl, index: number) { - if (!url.value || this.technicianIds[index] == this.clonedTechnicianIds[index]) { - return; - } - - delete this.clonedTechnicianIds[index]; - } - - technicianIdsEditCancel(url: PingUrl, index: number) { - this.technicianIds[index] = this.clonedTechnicianIds[index]; - delete this.clonedTechnicianIds[index]; - } } 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 61a5db6c..b92aa75b 100644 --- a/kdb-web/src/app/modules/shared/shared.module.ts +++ b/kdb-web/src/app/modules/shared/shared.module.ts @@ -25,6 +25,7 @@ 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({ @@ -33,6 +34,7 @@ import { DataViewModule, DataViewLayoutOptions } from 'primeng/dataview'; IpAddressPipe, BoolPipe, HistoryBtnComponent, + ConfigListComponent, ], imports: [ CommonModule, @@ -59,34 +61,35 @@ import { DataViewModule, DataViewLayoutOptions } from 'primeng/dataview'; 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, - DataViewModule, - DataViewLayoutOptions - ] + 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/i18n/de.json b/kdb-web/src/assets/i18n/de.json index e499fedf..f346df54 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -37,7 +37,7 @@ "header": "Bot", "help_url": "Befehlsreferenz", "ping_urls": "Ping Adressen", - "technicianIds": "Techniker Ids", + "technician_ids": "Techniker Ids", "wait_for_restart": "Wartezeit vor Neustart", "wait_for_shutdown": "Wartezeit vor Herunterfahren" }, @@ -156,7 +156,7 @@ "id": "Id", "leftServer": "Server verlassen", "messageId": "Nachricht Id", - "minXp": "Min. XP", + "min_xp": "Min. XP", "name": "Name", "operator": "Operator", "permissions": "Berechtigung", @@ -407,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 3d709daa..7dd4fa29 100644 --- a/kdb-web/src/assets/i18n/en.json +++ b/kdb-web/src/assets/i18n/en.json @@ -37,7 +37,7 @@ "header": "Bot", "help_url": "Help URL", "ping_urls": "Ping addresses", - "technicianIds": "Technician Ids", + "technician_ids": "Technician Ids", "wait_for_restart": "Time to wait before restart", "wait_for_shutdown": "Time to wait before shutdown" }, @@ -156,7 +156,7 @@ "id": "Id", "leftServer": "Left server", "messageId": "Message Id", - "minXp": "Min. XP", + "min_xp": "Min. XP", "name": "Name", "operator": "Operator", "permissions": "Permissions", @@ -407,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", @@ -487,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": { -- 2.45.2 From 51d95c81c17999a0c3e6884b8e824d4586742b5a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 7 Aug 2023 14:59:19 +0200 Subject: [PATCH 057/127] Added technician config to frontend #127 --- kdb-web/package.json | 2 +- kdb-web/src/app/models/graphql/queries.model.ts | 17 +++++++++++++++++ kdb-web/src/assets/config.json | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/kdb-web/package.json b/kdb-web/package.json index d6381d85..e9e0874b 100644 --- a/kdb-web/package.json +++ b/kdb-web/package.json @@ -51,4 +51,4 @@ "tslib": "^2.4.1", "typescript": "~4.9.5" } -} \ No newline at end of file +} diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts index 55998599..14f99354 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -1,5 +1,22 @@ export class Queries { + static technicianConfigQuery = ` + query technicianConfigQuery { + technicianConfig { + id + helpCommandReferenceUrl + waitForRestart + waitForShutdown + cacheMaxMessages + pingURLs + technicianIds + + createdAt + modifiedAt + } + } + `; + static guildsQuery = ` query GuildsQuery($id: ID) { guilds(filter: {id: $id}) { diff --git a/kdb-web/src/assets/config.json b/kdb-web/src/assets/config.json index 581bbcb8..9d35b928 100644 --- a/kdb-web/src/assets/config.json +++ b/kdb-web/src/assets/config.json @@ -25,4 +25,4 @@ "Name": "sh-edraft-dark-theme" } ] -} \ No newline at end of file +} -- 2.45.2 From bfe72668dc098270b8687c2a2dcd22cabe87d0fc Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 14 Aug 2023 18:44:07 +0200 Subject: [PATCH 058/127] Send message to team chat when a member leaves the server #295 --- kdb-bot/src/bot/translation/de.json | 1 + .../base/events/base_on_member_join_event.py | 2 +- .../events/base_on_member_remove_event.py | 24 +++++++++++++++---- .../base/events/base_on_message_event.py | 5 +++- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/kdb-bot/src/bot/translation/de.json b/kdb-bot/src/bot/translation/de.json index c4939ad7..82842240 100644 --- a/kdb-bot/src/bot/translation/de.json +++ b/kdb-bot/src/bot/translation/de.json @@ -151,6 +151,7 @@ } }, "base": { + "member_left_message": "{} hat uns leider verlassen :(", "complaints": { "title": "Beschwerde einreichen", "label": "Beschwerde", 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 8f8007f5..58af0a00 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 @@ -87,7 +87,7 @@ class BaseOnMemberJoinEvent(OnMemberJoinABC): return self._logger.debug(__name__, f"Add user: {member.id}") - self._users.add_user(User(member.id, 0, server)) + self._users.add_user(User(member.id, 0, 0, 0, server)) self._db.save_changes() user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) self._user_joins.add_user_joined_server(UserJoinedServer(user, datetime.now())) 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 8e565267..adfe7e87 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 @@ -2,6 +2,7 @@ from datetime import datetime from typing import Union import discord +from cpl_core.configuration import ConfigurationABC from cpl_core.database.context import DatabaseContextABC from cpl_core.logging import LoggerABC from cpl_discord.events import OnMemberRemoveABC @@ -12,14 +13,16 @@ 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 bot_data.model.server_config import ServerConfig class BaseOnMemberRemoveEvent(OnMemberRemoveABC): def __init__( self, + config: ConfigurationABC, logger: LoggerABC, db: DatabaseContextABC, - messenger: MessageServiceABC, + message_service: MessageServiceABC, users: UserRepositoryABC, servers: ServerRepositoryABC, user_joins: UserJoinedServerRepositoryABC, @@ -27,10 +30,10 @@ class BaseOnMemberRemoveEvent(OnMemberRemoveABC): ): OnMemberRemoveABC.__init__(self) + self._config = config self._logger = logger - self._base_helper = base_helper self._db = db - self._messenger = messenger + self._message_service = message_service self._users = users self._servers = servers self._user_joins = user_joins @@ -38,8 +41,7 @@ class BaseOnMemberRemoveEvent(OnMemberRemoveABC): async def _remove_user(self, member: Union[discord.User, discord.Member]): self._logger.debug(__name__, f"Remove user {member}") - 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) + await self._message_service.send_dm_message(self._t.transform("modules.base.goodbye_message"), member) try: server = self._servers.get_server_by_discord_id(member.guild.id) @@ -56,7 +58,19 @@ class BaseOnMemberRemoveEvent(OnMemberRemoveABC): except Exception as e: self._logger.error(__name__, f"Cannot remove user {member.id}", e) + async def _notify_team(self, member: discord.Member): + self._logger.debug(__name__, f"Notify team that a member left") + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{member.guild.id}") + channel = member.guild.get_channel(settings.team_channel_id) + await self._message_service.send_channel_message( + channel, + self._t.transform("modules.base.member_left_message").format(member.mention), + is_persistent=True, + ) + self._logger.trace(__name__, f"Notified team that a member left") + @EventChecks.check_is_ready() async def on_member_remove(self, member: discord.Member): self._logger.debug(__name__, f"Module {type(self)} started") await self._remove_user(member) + await self._notify_team(member) 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 61789132..e6531385 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 @@ -1,6 +1,7 @@ from typing import Optional import discord +from cpl_core.configuration import ConfigurationABC from cpl_core.database.context import DatabaseContextABC from cpl_discord.events import OnMessageABC from cpl_discord.service import DiscordBotServiceABC @@ -19,6 +20,7 @@ from bot_data.model.user import User class BaseOnMessageEvent(OnMessageABC): def __init__( self, + config: ConfigurationABC, logger: MessageLogger, client_utils: ClientUtilsService, db: DatabaseContextABC, @@ -28,6 +30,7 @@ class BaseOnMessageEvent(OnMessageABC): servers: ServerRepositoryABC, ): OnMessageABC.__init__(self) + self._config = config self._logger = logger self._client_utils = client_utils self._bot = bot @@ -63,7 +66,7 @@ class BaseOnMessageEvent(OnMessageABC): self._logger.error(__name__, f"User not found {dc_user_id}") return - settings: ServerConfig = se + settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{server.discord_id}") if self._client_utils.is_message_xp_count_by_hour_higher_that_max_message_count_per_hour( message.created_at, user, settings ): -- 2.45.2 From 1f9991eeda2910312f79e3d5867c663fd7a8a667 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 14 Aug 2023 19:12:37 +0200 Subject: [PATCH 059/127] Fixed queries #295 --- .../src/app/models/graphql/queries.model.ts | 61 +++++++------------ 1 file changed, 22 insertions(+), 39 deletions(-) diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts index 14f99354..4f6856b4 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -1,22 +1,5 @@ export class Queries { - static technicianConfigQuery = ` - query technicianConfigQuery { - technicianConfig { - id - helpCommandReferenceUrl - waitForRestart - waitForShutdown - cacheMaxMessages - pingURLs - technicianIds - - createdAt - modifiedAt - } - } - `; - static guildsQuery = ` query GuildsQuery($id: ID) { guilds(filter: {id: $id}) { @@ -382,31 +365,31 @@ export class Queries { 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 { + name + config { id + messageDeleteTimer + notificationChatId + maxVoiceStateHours + xpPerMessage + xpPerReaction + maxMessageXpPerHour + xpPerOntimeHour + xpPerEventParticipation + xpPerAchievement + afkCommandChannelId + helpVoiceChannelId + teamChannelId + loginMessageChannelId + afkChannelIds + moderatorRoleIds + adminRoleIds + + server { + id + } } } } - } `; } -- 2.45.2 From 44e225c273f353f2ac9f6cdd451d3d4cc001ab97 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 14 Aug 2023 19:25:12 +0200 Subject: [PATCH 060/127] Fixed code after merges #1.1.0 --- ...se_on_voice_state_update_event_scheduled_event_bonus.py | 4 ---- kdb-bot/src/modules/base/service/event_service.py | 7 ++----- 2 files changed, 2 insertions(+), 9 deletions(-) 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 641f8ddb..fe5195c9 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,6 @@ 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 modules.base.service.event_service import EventService @@ -17,7 +15,6 @@ class BaseOnVoiceStateUpdateEventScheduledEventBonus(OnVoiceStateUpdateABC): self, config: ConfigurationABC, logger: LoggerABC, - base_helper: BaseHelperABC, servers: ServerRepositoryABC, users: UserRepositoryABC, events: EventService, @@ -26,7 +23,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 diff --git a/kdb-bot/src/modules/base/service/event_service.py b/kdb-bot/src/modules/base/service/event_service.py index d5c77360..30b19d96 100644 --- a/kdb-bot/src/modules/base/service/event_service.py +++ b/kdb-bot/src/modules/base/service/event_service.py @@ -8,9 +8,8 @@ from cpl_query.extension import List from bot_data.abc.server_repository_abc import ServerRepositoryABC from bot_data.abc.user_repository_abc import UserRepositoryABC -from modules.base.configuration.base_server_settings import BaseServerSettings +from bot_data.model.server_config import ServerConfig from modules.base.model.active_event import ActiveEvent -from modules.base.service.base_helper_service import BaseHelperService class EventService: @@ -18,14 +17,12 @@ class EventService: self, config: ConfigurationABC, logger: LoggerABC, - base_helper: BaseHelperService, servers: ServerRepositoryABC, users: UserRepositoryABC, db: DatabaseContextABC, ): self._config = config self._logger = logger - self._base_helper = base_helper self._servers = servers self._users = users self._db = db @@ -59,7 +56,7 @@ class EventService: 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() -- 2.45.2 From 9db00516c3590e3176f2a673f52eee3141425607 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 14 Aug 2023 19:36:22 +0200 Subject: [PATCH 061/127] Fixed translations #1.1.0 --- kdb-web/package.json | 4 ++-- .../server/config/components/config/config.component.ts | 2 +- kdb-web/src/app/services/sidebar/sidebar.service.ts | 2 +- kdb-web/src/assets/i18n/de.json | 7 ++++++- kdb-web/src/assets/i18n/en.json | 7 ++++++- kdb-web/src/assets/version.json | 4 ++-- 6 files changed, 18 insertions(+), 8 deletions(-) diff --git a/kdb-web/package.json b/kdb-web/package.json index e9e0874b..fc35367e 100644 --- a/kdb-web/package.json +++ b/kdb-web/package.json @@ -1,6 +1,6 @@ { "name": "kdb-web", - "version": "1.0.dev294_frontend_version", + "version": "1.1.0", "scripts": { "ng": "ng", "update-version": "ts-node-esm update-version.ts", @@ -51,4 +51,4 @@ "tslib": "^2.4.1", "typescript": "~4.9.5" } -} +} \ No newline at end of file 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 index 0de50e7c..0769ea57 100644 --- 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 @@ -110,7 +110,7 @@ export class ConfigComponent implements OnInit { 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")); + this.toastService.success(this.translate.instant("view.server.config.message.server_config_create"), this.translate.instant("view.server.config.message.server_config_create_d")); }); } } diff --git a/kdb-web/src/app/services/sidebar/sidebar.service.ts b/kdb-web/src/app/services/sidebar/sidebar.service.ts index 196b7e25..5654a30e 100644 --- a/kdb-web/src/app/services/sidebar/sidebar.service.ts +++ b/kdb-web/src/app/services/sidebar/sidebar.service.ts @@ -112,7 +112,7 @@ export class SidebarService { }; this.serverConfig = { - label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.config") : "", + label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.configuration") : "", icon: "pi pi-cog", visible: true, routerLink: `server/${this.server$.value?.id}/config` diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index f346df54..b67922a8 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -296,6 +296,7 @@ "server": { "achievements": "Errungenschaften", "auto_roles": "Auto Rollen", + "configuration": "Konfiguration", "dashboard": "Dashboard", "levels": "Level", "members": "Mitglieder", @@ -427,7 +428,11 @@ "xp_per_ontime_hour": "XP für eine Stunde im Sprachkanal", "xp_per_reaction": "XP für eine Reaktion" }, - "header": "Server Konfiguration" + "header": "Server Konfiguration", + "message": { + "server_config_create": "Konfiguration gespeichert", + "server_config_create_d": "Server Konfiguration erfolgreich gespeichert" + } }, "dashboard": { "deleted_message_count": "Gelöschte Nachrichten", diff --git a/kdb-web/src/assets/i18n/en.json b/kdb-web/src/assets/i18n/en.json index 7dd4fa29..821996db 100644 --- a/kdb-web/src/assets/i18n/en.json +++ b/kdb-web/src/assets/i18n/en.json @@ -296,6 +296,7 @@ "server": { "achievements": "Achievements", "auto_roles": "Auto role", + "configuration": "Configuration", "dashboard": "Dashboard", "levels": "Level", "members": "Members", @@ -427,7 +428,11 @@ "xp_per_ontime_hour": "XP for one hour in an voice channel", "xp_per_reaction": "XP for an reaction" }, - "header": "Server configuration" + "header": "Server configuration", + "message": { + "server_config_create": "Config saved", + "server_config_create_d": "Saved server config successfully" + } }, "dashboard": { "deleted_message_count": "Deleted messages", diff --git a/kdb-web/src/assets/version.json b/kdb-web/src/assets/version.json index 8d4c9ae3..71ae202d 100644 --- a/kdb-web/src/assets/version.json +++ b/kdb-web/src/assets/version.json @@ -1,7 +1,7 @@ { "WebVersion": { "Major": "1", - "Minor": "0", - "Micro": "dev294_frontend_version" + "Minor": "1", + "Micro": "0" } } \ No newline at end of file -- 2.45.2 From e6c99593811eaabc5b138957d60d65ffe10bfe0d Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 14 Aug 2023 20:57:59 +0200 Subject: [PATCH 062/127] Added filter to mass_move channel_from #296 --- kdb-bot/src/bot/module_list.py | 2 +- .../modules/base/command/mass_move_command.py | 4 ++- .../base/helper/voice_channel_transformer.py | 30 +++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 kdb-bot/src/modules/base/helper/voice_channel_transformer.py diff --git a/kdb-bot/src/bot/module_list.py b/kdb-bot/src/bot/module_list.py index aee830ef..3e5fea34 100644 --- a/kdb-bot/src/bot/module_list.py +++ b/kdb-bot/src/bot/module_list.py @@ -25,8 +25,8 @@ class ModuleList: [ CoreModule, # has to be first! DataModule, + ConfigModule, # has to be before db check DatabaseModule, - ConfigModule, # has be to after db check GraphQLModule, PermissionModule, AutoRoleModule, diff --git a/kdb-bot/src/modules/base/command/mass_move_command.py b/kdb-bot/src/modules/base/command/mass_move_command.py index dca23d73..4dd835d2 100644 --- a/kdb-bot/src/modules/base/command/mass_move_command.py +++ b/kdb-bot/src/modules/base/command/mass_move_command.py @@ -4,6 +4,7 @@ import discord from cpl_discord.command import DiscordCommandABC from cpl_discord.service import DiscordBotServiceABC from cpl_translation import TranslatePipe +from discord.app_commands import Transform from discord.ext import commands from discord.ext.commands import Context @@ -11,6 +12,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_core.service.client_utils_service import ClientUtilsService +from modules.base.helper.voice_channel_transformer import VoiceChannelTransformer class MassMoveCommand(DiscordCommandABC): @@ -36,7 +38,7 @@ class MassMoveCommand(DiscordCommandABC): self, ctx: Context, channel_to: discord.VoiceChannel, - channel_from: discord.VoiceChannel = None, + channel_from: Transform[str, VoiceChannelTransformer] = None, ): self._logger.debug(__name__, f"Received command mass-move {ctx}") diff --git a/kdb-bot/src/modules/base/helper/voice_channel_transformer.py b/kdb-bot/src/modules/base/helper/voice_channel_transformer.py new file mode 100644 index 00000000..a9ee5df0 --- /dev/null +++ b/kdb-bot/src/modules/base/helper/voice_channel_transformer.py @@ -0,0 +1,30 @@ +import discord +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_query.extension import List +from discord import Interaction, app_commands +from discord.app_commands import Transformer, Choice + +from bot_core.abc.client_utils_abc import ClientUtilsABC + + +class VoiceChannelTransformer(Transformer): + async def transform(self, interaction: Interaction, value: str, /) -> discord.VoiceChannel: + voice_channel = ( + List(discord.VoiceChannel, interaction.guild.voice_channels) + .where(lambda x: str(x.id) == value) + .first_or_default() + ) + return voice_channel + + async def autocomplete(self, interaction: Interaction, current: str, /) -> list[Choice[str]]: + @ServiceProviderABC.inject + def get_client_utils(client_utils: ClientUtilsABC) -> ClientUtilsABC: + return client_utils + + voice_channels = List(discord.Role, interaction.guild.voice_channels).where(lambda x: len(x.members) > 0) + return [ + app_commands.Choice( + name=f"{vc.name}" if vc.category is None else f"{vc.name}: {vc.category.name}", value=vc.name + ) + for vc in get_client_utils().get_auto_complete_list(voice_channels, current, lambda x: x.name) + ] -- 2.45.2 From 4add293186e4abc34d79020568ee75f7dd560110 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 14 Aug 2023 23:33:02 +0200 Subject: [PATCH 063/127] Added base logic to hide columns & added hide columns to levels #79 --- kdb-web/package.json | 2 +- .../src/app/base/component-with-table.spec.ts | 7 ++ kdb-web/src/app/base/component-with-table.ts | 39 ++++++++++ .../src/app/modules/shared/shared.module.ts | 74 ++++++++++--------- .../components/config/config.component.ts | 2 +- .../components/levels/levels.component.html | 44 ++++++----- .../components/levels/levels.component.ts | 12 +-- kdb-web/src/assets/i18n/de.json | 1 + kdb-web/src/assets/i18n/en.json | 1 + kdb-web/src/assets/version.json | 2 +- kdb-web/src/styles.scss | 17 ++++- .../src/styles/themes/default-dark-theme.scss | 53 ++++++++++++- .../styles/themes/default-light-theme.scss | 53 ++++++++++++- .../styles/themes/sh-edraft-dark-theme.scss | 53 ++++++++++++- .../styles/themes/sh-edraft-light-theme.scss | 53 ++++++++++++- 15 files changed, 347 insertions(+), 66 deletions(-) create mode 100644 kdb-web/src/app/base/component-with-table.spec.ts create mode 100644 kdb-web/src/app/base/component-with-table.ts diff --git a/kdb-web/package.json b/kdb-web/package.json index fc35367e..bfe9eed3 100644 --- a/kdb-web/package.json +++ b/kdb-web/package.json @@ -1,6 +1,6 @@ { "name": "kdb-web", - "version": "1.1.0", + "version": "1.1.dev79_hide_table_attributes", "scripts": { "ng": "ng", "update-version": "ts-node-esm update-version.ts", diff --git a/kdb-web/src/app/base/component-with-table.spec.ts b/kdb-web/src/app/base/component-with-table.spec.ts new file mode 100644 index 00000000..5b08b905 --- /dev/null +++ b/kdb-web/src/app/base/component-with-table.spec.ts @@ -0,0 +1,7 @@ +import { ComponentWithTable } from './component-with-table'; + +describe('ComponentWithTable', () => { + it('should create an instance', () => { + expect(new ComponentWithTable()).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/base/component-with-table.ts b/kdb-web/src/app/base/component-with-table.ts new file mode 100644 index 00000000..97828341 --- /dev/null +++ b/kdb-web/src/app/base/component-with-table.ts @@ -0,0 +1,39 @@ +interface Column { + key: string; + name: string; +} + +export class ComponentWithTable { + + private _hiddenColumns: Column[] = []; + set hiddenColumns(value: Column[]) { + this._hiddenColumns = value; + localStorage.setItem("hiddenColumns", JSON.stringify(value)); + } + + get hiddenColumns(): Column[] { + return this._hiddenColumns; + } + + private name: string = ""; + public columns: Column[] = []; + + constructor( + name: string, + columns: string[] + ) { + this.name = name; + this.columns = columns.map(column => { + return { key: this.getKey(column), name: column }; + }); + this._hiddenColumns = JSON.parse(localStorage.getItem("hiddenColumns") ?? ""); + } + + private getKey(column: string): string { + return `${this.name}_${column}`; + } + + public isColumnVisible(column: string): boolean { + return !this._hiddenColumns.map(column => column.key).includes(this.getKey(column)); + } +} diff --git a/kdb-web/src/app/modules/shared/shared.module.ts b/kdb-web/src/app/modules/shared/shared.module.ts index b92aa75b..68eb5b71 100644 --- a/kdb-web/src/app/modules/shared/shared.module.ts +++ b/kdb-web/src/app/modules/shared/shared.module.ts @@ -23,9 +23,10 @@ import { PanelModule } from "primeng/panel"; 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'; +import { HistoryBtnComponent } from "./components/history-btn/history-btn.component"; +import { DataViewModule, DataViewLayoutOptions } from "primeng/dataview"; +import { ConfigListComponent } from "./components/config-list/config-list.component"; +import { MultiSelectModule } from "primeng/multiselect"; @NgModule({ @@ -34,7 +35,7 @@ import { ConfigListComponent } from './components/config-list/config-list.compon IpAddressPipe, BoolPipe, HistoryBtnComponent, - ConfigListComponent, + ConfigListComponent ], imports: [ CommonModule, @@ -60,36 +61,39 @@ import { ConfigListComponent } from './components/config-list/config-list.compon ImageModule, SidebarModule, DataViewModule, + MultiSelectModule ], - 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 - ] + 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, + MultiSelectModule + ] }) -export class SharedModule { } +export class SharedModule { +} 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 index 0769ea57..7e2a0f1d 100644 --- 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 @@ -110,7 +110,7 @@ export class ConfigComponent implements OnInit { return throwError(err); })).subscribe(result => { this.spinner.hideSpinner(); - this.toastService.success(this.translate.instant("view.server.config.message.server_config_create"), this.translate.instant("view.server.config.message.server_config_create_d")); + this.toastService.success(this.translate.instant("view.server.config.message.server#_config_create"), this.translate.instant("view.server.config.message.server_config_create_d")); }); } } diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html index 0c8b1945..114143e0 100644 --- a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html +++ b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html @@ -9,11 +9,21 @@
-
- {{levels.length}} {{'common.of' | translate}} - {{dt.totalRecords}} - - {{'view.server.levels.levels' | translate}} +
+
+ {{levels.length}} {{'common.of' | translate}} + {{dt.totalRecords}} + + {{'view.server.levels.levels' | translate}} +
+ +
+ + +
{{'view.server.levels.headers.' + item.name | translate}}
+
+
+
@@ -36,28 +46,28 @@
- +
{{'view.server.levels.headers.name' | translate}}
- +
{{'view.server.levels.headers.color' | translate}}
- +
{{'view.server.levels.headers.min_xp' | translate}}
- +
{{'view.server.levels.headers.permissions' | translate}}
@@ -90,15 +100,15 @@ placeholder="{{'common.id' | translate}}"> - +
- - - + + + @@ -118,7 +128,7 @@ - + @@ -129,7 +139,7 @@ - + @@ -140,7 +150,7 @@ - + @@ -151,7 +161,7 @@ - + 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 63e1e446..1a5461a6 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 @@ -22,14 +22,14 @@ import { Mutations } from "../../../../../../models/graphql/mutations.model"; import { Subject, throwError } from "rxjs"; import { Server } from "../../../../../../models/data/server.model"; import { UserDTO } from "../../../../../../models/auth/auth-user.dto"; +import { ComponentWithTable } from "../../../../../../base/component-with-table"; @Component({ selector: "app-levels", templateUrl: "./levels.component.html", styleUrls: ["./levels.component.scss"] }) -export class LevelsComponent implements OnInit, OnDestroy { - +export class LevelsComponent extends ComponentWithTable implements OnInit, OnDestroy { public levels: Level[] = []; public loading = true; @@ -72,7 +72,9 @@ export class LevelsComponent implements OnInit, OnDestroy { private translate: TranslateService, private data: DataService, private sidebar: SidebarService, - private route: ActivatedRoute) { + private route: ActivatedRoute + ) { + super("level", ["name", "color", "min_xp", "permissions"]); } public ngOnInit(): void { @@ -96,8 +98,8 @@ export class LevelsComponent implements OnInit, OnDestroy { serverId: this.server.id, filter: this.filter, page: this.page, sort: this.sort }, (data: Query) => { - return data.servers[0]; - } + return data.servers[0]; + } ).subscribe(data => { this.totalRecords = data.levelCount; this.levels = data.levels; diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index b67922a8..ec3aa22a 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -142,6 +142,7 @@ "discord_id": "Discord Id", "email": "E-Mail", "error": "Fehler", + "hidden_columns": "Ausgeblendete Spalten", "history": { "attribute": "Attribut", "autoRole": "Auto Rolle", diff --git a/kdb-web/src/assets/i18n/en.json b/kdb-web/src/assets/i18n/en.json index 821996db..cfc8e077 100644 --- a/kdb-web/src/assets/i18n/en.json +++ b/kdb-web/src/assets/i18n/en.json @@ -142,6 +142,7 @@ "discord_id": "Discord Id", "email": "E-Mail", "error": "Error", + "hidden_columns": "Hidden columns", "history": { "attribute": "Attribute", "autoRole": "Auto role", diff --git a/kdb-web/src/assets/version.json b/kdb-web/src/assets/version.json index 71ae202d..4a930e41 100644 --- a/kdb-web/src/assets/version.json +++ b/kdb-web/src/assets/version.json @@ -2,6 +2,6 @@ "WebVersion": { "Major": "1", "Minor": "1", - "Micro": "0" + "Micro": "dev79_hide_table_attributes" } } \ No newline at end of file diff --git a/kdb-web/src/styles.scss b/kdb-web/src/styles.scss index 71be66ee..af15846a 100644 --- a/kdb-web/src/styles.scss +++ b/kdb-web/src/styles.scss @@ -241,9 +241,22 @@ header { .table-caption { display: flex; - .table-caption-text { + .table-caption-table-info { + display: flex; flex: 1; - font-weight: 400; + flex-direction: row; + gap: 25px; + + .table-caption-text { + display: flex; + align-items: center; + + font-weight: 400; + } + + .table-caption-column-select { + flex: 1; + } } .table-caption-search { diff --git a/kdb-web/src/styles/themes/default-dark-theme.scss b/kdb-web/src/styles/themes/default-dark-theme.scss index 5222645f..45fa4f2f 100644 --- a/kdb-web/src/styles/themes/default-dark-theme.scss +++ b/kdb-web/src/styles/themes/default-dark-theme.scss @@ -386,7 +386,12 @@ color: $primaryTextColor !important; .table-caption { - .table-caption-text { + .table-caption-table-info { + .table-caption-text { + } + + .table-caption-column-select { + } } .table-caption-search-wrapper { @@ -611,4 +616,50 @@ } } } + + .p-multiselect { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + + &:focus, + &.p-focus, + &:not(.p-disabled):hover { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + } + + .p-multiselect-panel { + .p-multiselect-header { + background-color: $primaryBackgroundColor !important; + } + + .p-multiselect-items, + .p-multiselect-item { + background-color: $secondaryBackgroundColor !important; + } + + .p-multiselect-item { + color: $primaryTextColor !important; + border: 1px solid transparent !important; + + &:hover { + border: 1px solid $primaryHeaderColor !important; + color: $primaryHeaderColor !important; + } + + &:focus { + box-shadow: none !important; + } + } + + .p-checkbox .p-checkbox-box.p-highlight { + border-color: $primaryHeaderColor !important; + background: $primaryHeaderColor !important; + } + + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { + border-color: $primaryHeaderColor !important; + } + } + } } diff --git a/kdb-web/src/styles/themes/default-light-theme.scss b/kdb-web/src/styles/themes/default-light-theme.scss index 1e7078e2..82341a81 100644 --- a/kdb-web/src/styles/themes/default-light-theme.scss +++ b/kdb-web/src/styles/themes/default-light-theme.scss @@ -386,7 +386,12 @@ color: $primaryTextColor !important; .table-caption { - .table-caption-text { + .table-caption-table-info { + .table-caption-text { + } + + .table-caption-column-select { + } } .table-caption-search-wrapper { @@ -611,4 +616,50 @@ } } } + + .p-multiselect { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + + &:focus, + &.p-focus, + &:not(.p-disabled):hover { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + } + + .p-multiselect-panel { + .p-multiselect-header { + background-color: $secondaryBackgroundColor !important; + } + + .p-multiselect-items, + .p-multiselect-item { + background-color: $primaryBackgroundColor !important; + } + + .p-multiselect-item { + color: $primaryTextColor !important; + border: 1px solid transparent !important; + + &:hover { + border: 1px solid $primaryHeaderColor !important; + color: $primaryHeaderColor !important; + } + + &:focus { + box-shadow: none !important; + } + } + + .p-checkbox .p-checkbox-box.p-highlight { + border-color: $primaryHeaderColor !important; + background: $primaryHeaderColor !important; + } + + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { + border-color: $primaryHeaderColor !important; + } + } + } } diff --git a/kdb-web/src/styles/themes/sh-edraft-dark-theme.scss b/kdb-web/src/styles/themes/sh-edraft-dark-theme.scss index 42e926ff..60974511 100644 --- a/kdb-web/src/styles/themes/sh-edraft-dark-theme.scss +++ b/kdb-web/src/styles/themes/sh-edraft-dark-theme.scss @@ -390,7 +390,12 @@ color: $primaryTextColor !important; .table-caption { - .table-caption-text { + .table-caption-table-info { + .table-caption-text { + } + + .table-caption-column-select { + } } .table-caption-search-wrapper { @@ -619,4 +624,50 @@ } } } + + .p-multiselect { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + + &:focus, + &.p-focus, + &:not(.p-disabled):hover { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + } + + .p-multiselect-panel { + .p-multiselect-header { + background-color: $primaryBackgroundColor !important; + } + + .p-multiselect-items, + .p-multiselect-item { + background-color: $secondaryBackgroundColor !important; + } + + .p-multiselect-item { + color: $primaryTextColor !important; + border: 1px solid transparent !important; + + &:hover { + border: 1px solid $primaryHeaderColor !important; + color: $primaryHeaderColor !important; + } + + &:focus { + box-shadow: none !important; + } + } + + .p-checkbox .p-checkbox-box.p-highlight { + border-color: $primaryHeaderColor !important; + background: $primaryHeaderColor !important; + } + + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { + border-color: $primaryHeaderColor !important; + } + } + } } diff --git a/kdb-web/src/styles/themes/sh-edraft-light-theme.scss b/kdb-web/src/styles/themes/sh-edraft-light-theme.scss index 8fa8f2fb..ebf9360d 100644 --- a/kdb-web/src/styles/themes/sh-edraft-light-theme.scss +++ b/kdb-web/src/styles/themes/sh-edraft-light-theme.scss @@ -386,7 +386,12 @@ color: $primaryTextColor !important; .table-caption { - .table-caption-text { + .table-caption-table-info { + .table-caption-text { + } + + .table-caption-column-select { + } } .table-caption-search-wrapper { @@ -611,4 +616,50 @@ } } } + + .p-multiselect { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + + &:focus, + &.p-focus, + &:not(.p-disabled):hover { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + } + + .p-multiselect-panel { + .p-multiselect-header { + background-color: $secondaryBackgroundColor !important; + } + + .p-multiselect-items, + .p-multiselect-item { + background-color: $primaryBackgroundColor !important; + } + + .p-multiselect-item { + color: $primaryTextColor !important; + border: 1px solid transparent !important; + + &:hover { + border: 1px solid $primaryHeaderColor !important; + color: $primaryHeaderColor !important; + } + + &:focus { + box-shadow: none !important; + } + } + + .p-checkbox .p-checkbox-box.p-highlight { + border-color: $primaryHeaderColor !important; + background: $primaryHeaderColor !important; + } + + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { + border-color: $primaryHeaderColor !important; + } + } + } } -- 2.45.2 From 8d76f797320677cb4b1ea0881c391348b172207b Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 15 Aug 2023 08:14:45 +0200 Subject: [PATCH 064/127] Hide members columns #79 --- kdb-web/package.json | 2 +- .../components/levels/levels.component.html | 18 ++--- .../components/levels/levels.component.ts | 2 +- .../server/members/members.component.html | 80 +++++++++++-------- .../view/server/members/members.component.ts | 14 ++-- kdb-web/src/assets/i18n/de.json | 36 ++++----- kdb-web/src/assets/version.json | 2 +- 7 files changed, 80 insertions(+), 74 deletions(-) diff --git a/kdb-web/package.json b/kdb-web/package.json index bfe9eed3..998a4411 100644 --- a/kdb-web/package.json +++ b/kdb-web/package.json @@ -1,6 +1,6 @@ { "name": "kdb-web", - "version": "1.1.dev79_hide_table_attributes", + "version": "1.1.dev79_hide_table_columns", "scripts": { "ng": "ng", "update-version": "ts-node-esm update-version.ts", diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html index 114143e0..9e059391 100644 --- a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html +++ b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html @@ -20,7 +20,7 @@
-
{{'view.server.levels.headers.' + item.name | translate}}
+
{{'common.' + item.name | translate}}
@@ -39,7 +39,7 @@ - +
{{'common.id' | translate}}
@@ -48,28 +48,28 @@
-
{{'view.server.levels.headers.name' | translate}}
+
{{'common.name' | translate}}
-
{{'view.server.levels.headers.color' | translate}}
+
{{'common.color' | translate}}
-
{{'view.server.levels.headers.min_xp' | translate}}
+
{{'common.min_xp' | translate}}
-
{{'view.server.levels.headers.permissions' | translate}}
+
{{'common.permissions' | translate}}
@@ -94,7 +94,7 @@ - +
@@ -103,7 +103,7 @@ + placeholder="{{'common.name' | translate}}">
@@ -117,7 +117,7 @@ - + {{level.id}} 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 1a5461a6..4ae5bb94 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 @@ -74,7 +74,7 @@ export class LevelsComponent extends ComponentWithTable implements OnInit, OnDes private sidebar: SidebarService, private route: ActivatedRoute ) { - super("level", ["name", "color", "min_xp", "permissions"]); + super("level", ["id", "name", "color", "min_xp", "permissions"]); } public ngOnInit(): void { diff --git a/kdb-web/src/app/modules/view/server/members/members.component.html b/kdb-web/src/app/modules/view/server/members/members.component.html index cc51f4a2..ea3d2e52 100644 --- a/kdb-web/src/app/modules/view/server/members/members.component.html +++ b/kdb-web/src/app/modules/view/server/members/members.component.html @@ -9,11 +9,21 @@
-
- {{members.length}} {{'common.of' | translate}} - {{dt.totalRecords}} - - {{'view.server.members.members' | translate}} +
+
+ {{members.length}} {{'common.of' | translate}} + {{dt.totalRecords}} + + {{'view.server.members.members' | translate}} +
+ +
+ + +
{{'common.' + item.name | translate}}
+
+
+
@@ -26,51 +36,51 @@ - +
{{'common.id' | translate}}
- +
{{'common.discord_id' | translate}}
- +
-
{{'view.server.members.headers.name' | translate}}
+
{{'common.name' | translate}}
- +
-
{{'view.server.members.headers.xp' | translate}}
+
{{'common.xp' | translate}}
- +
-
{{'view.server.members.headers.ontime' | translate}}
+
{{'common.ontime' | translate}}
- +
-
{{'view.server.members.headers.left_server' | translate}}
+
{{'common.left_server' | translate}}
- +
-
{{'view.server.members.headers.level' | translate}}
+
{{'common.level' | translate}}
@@ -95,31 +105,31 @@ - +
- +
- +
- +
- - - + + +
- +
- +
- +
@@ -130,7 +140,7 @@ - + {{member.id}} @@ -140,7 +150,7 @@ - + {{member.discordId}} @@ -150,7 +160,7 @@ - + {{member.name}} @@ -160,7 +170,7 @@ - + - + {{member.ontime}} @@ -182,7 +192,7 @@ - + {{!member.leftServer | bool}} @@ -192,10 +202,10 @@ - + - + {{member.level.name}} 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 e46afb61..6786adad 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 @@ -20,19 +20,17 @@ import { UpdateUserMutationResult } from "../../../../models/graphql/result.mode import { ActivatedRoute } from "@angular/router"; import { Level } from "../../../../models/data/level.model"; import { Server } from "../../../../models/data/server.model"; +import { ComponentWithTable } from "../../../../base/component-with-table"; @Component({ selector: "app-members", templateUrl: "./members.component.html", styleUrls: ["./members.component.scss"] }) -export class MembersComponent implements OnInit, OnDestroy { +export class MembersComponent extends ComponentWithTable implements OnInit, OnDestroy { members!: User[]; levels!: MenuItem[]; - leftServerOptions = [ - { label: this.translate.instant("common.bool_as_string.true"), value: false }, - { label: this.translate.instant("common.bool_as_string.false"), value: true } - ]; + leftServerOptions: { label: string; value: boolean; }[] = []; loading = true; clonedUsers: { [s: string]: User; } = {}; @@ -93,6 +91,7 @@ export class MembersComponent implements OnInit, OnDestroy { private data: DataService, private route: ActivatedRoute ) { + super("member", ["id", "discord_id", "name", "xp", "ontime", "left_server", "level"]); } ngOnInit(): void { @@ -112,9 +111,14 @@ export class MembersComponent implements OnInit, OnDestroy { return { label: level.name, value: level }; }); }); + this.leftServerOptions = [ + { label: this.translate.instant("common.bool_as_string.true"), value: false }, + { label: this.translate.instant("common.bool_as_string.false"), value: true } + ]; this.loadNextPage(); }); } + public ngOnDestroy(): void { this.unsubscriber.next(); this.unsubscriber.complete(); diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index ec3aa22a..9659ea62 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -2,15 +2,6 @@ "admin": { "auth_users": { "header": "Benutzer", - "headers": { - "active": "Aktiv", - "auth_role": "Rolle", - "first_name": "Vorname", - "last_name": "Nachname", - "password": "Passwort", - "role": "Rolle", - "users": "Benutzer" - }, "message": { "cannot_delete_user": "Benutzer kann nicht gelöscht werden", "invalid_email": "Ungültige E-Mail", @@ -131,6 +122,20 @@ } }, "common": { + "active": "Aktiv", + "auth_role": "Rolle", + "first_name": "Vorname", + "last_name": "Nachname", + "password": "Passwort", + "role": "Rolle", + "users": "Benutzer", + "color": "Farbe", + "min_xp": "Min. XP", + "permissions": "Rechte", + "left_server": "Aktiv", + "level": "Level", + "ontime": "Ontime", + "xp": "XP", "404": "404 - Der Eintrag konnte nicht gefunden werden", "actions": "Aktionen", "add": "Hinzufügen", @@ -447,12 +452,6 @@ "header": "Server", "levels": { "header": "Level", - "headers": { - "color": "Farbe", - "min_xp": "Min. XP", - "name": "Name", - "permissions": "Rechte" - }, "levels": "Level", "message": { "level_create": "Level erstellt", @@ -473,13 +472,6 @@ }, "members": { "header": "Mitglieder", - "headers": { - "left_server": "Aktiv", - "level": "Level", - "name": "Name", - "ontime": "Ontime", - "xp": "XP" - }, "members": "Mitgliedern", "message": { "user_change_failed": "Benutzeränderung fehlgeschlagen", diff --git a/kdb-web/src/assets/version.json b/kdb-web/src/assets/version.json index 4a930e41..d2369dd9 100644 --- a/kdb-web/src/assets/version.json +++ b/kdb-web/src/assets/version.json @@ -2,6 +2,6 @@ "WebVersion": { "Major": "1", "Minor": "1", - "Micro": "dev79_hide_table_attributes" + "Micro": "dev79_hide_table_columns" } } \ No newline at end of file -- 2.45.2 From bfc9979961dad34fc6c6e06fdc665ed9ef84c94b Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 15 Aug 2023 12:16:24 +0200 Subject: [PATCH 065/127] Added option to hide columns to all tables #79 --- .../service/auth_user_repository_service.py | 13 +++- kdb-web/src/app/base/component-with-table.ts | 2 +- .../auth-user/auth-user.component.html | 65 +++++++++-------- .../auth-user/auth-user.component.ts | 4 +- .../shared/base/hideable-component.spec.ts | 7 ++ .../modules/shared/base/hideable-component.ts | 13 ++++ .../multi-select-columns.component.html | 16 +++++ .../multi-select-columns.component.scss | 0 .../multi-select-columns.component.spec.ts | 23 ++++++ .../multi-select-columns.component.ts | 24 +++++++ .../hideable-column.component.html | 1 + .../hideable-column.component.scss | 1 + .../hideable-column.component.spec.ts | 23 ++++++ .../hideable-column.component.ts | 16 +++++ .../hideable-header.component.html | 11 +++ .../hideable-header.component.scss | 0 .../hideable-header.component.spec.ts | 23 ++++++ .../hideable-header.component.ts | 16 +++++ .../src/app/modules/shared/shared.module.ts | 17 +++-- .../achievement/achievement.component.html | 70 ++++++++++--------- .../achievement/achievement.component.ts | 6 +- .../auto-roles-rules.component.html | 43 ++++++------ .../auto-roles-rules.component.ts | 4 +- .../auto-roles/auto-roles.component.html | 66 +++++++++-------- .../auto-roles/auto-roles.component.ts | 4 +- .../components/levels/levels.component.html | 38 +++++----- .../server/members/members.component.html | 50 ++++++------- kdb-web/src/assets/i18n/de.json | 56 +++++++-------- kdb-web/src/assets/i18n/en.json | 64 +++++++---------- kdb-web/src/styles.scss | 4 ++ .../styles/themes/sh-edraft-dark-theme.scss | 4 +- 31 files changed, 435 insertions(+), 249 deletions(-) create mode 100644 kdb-web/src/app/modules/shared/base/hideable-component.spec.ts create mode 100644 kdb-web/src/app/modules/shared/base/hideable-component.ts create mode 100644 kdb-web/src/app/modules/shared/base/multi-select-columns/multi-select-columns.component.html create mode 100644 kdb-web/src/app/modules/shared/base/multi-select-columns/multi-select-columns.component.scss create mode 100644 kdb-web/src/app/modules/shared/base/multi-select-columns/multi-select-columns.component.spec.ts create mode 100644 kdb-web/src/app/modules/shared/base/multi-select-columns/multi-select-columns.component.ts create mode 100644 kdb-web/src/app/modules/shared/components/hideable-column/hideable-column.component.html create mode 100644 kdb-web/src/app/modules/shared/components/hideable-column/hideable-column.component.scss create mode 100644 kdb-web/src/app/modules/shared/components/hideable-column/hideable-column.component.spec.ts create mode 100644 kdb-web/src/app/modules/shared/components/hideable-column/hideable-column.component.ts create mode 100644 kdb-web/src/app/modules/shared/components/hideable-header/hideable-header.component.html create mode 100644 kdb-web/src/app/modules/shared/components/hideable-header/hideable-header.component.scss create mode 100644 kdb-web/src/app/modules/shared/components/hideable-header/hideable-header.component.spec.ts create mode 100644 kdb-web/src/app/modules/shared/components/hideable-header/hideable-header.component.ts diff --git a/kdb-bot/src/bot_data/service/auth_user_repository_service.py b/kdb-bot/src/bot_data/service/auth_user_repository_service.py index 295e3c2f..87b39169 100644 --- a/kdb-bot/src/bot_data/service/auth_user_repository_service.py +++ b/kdb-bot/src/bot_data/service/auth_user_repository_service.py @@ -1,3 +1,4 @@ +from enum import Enum from typing import Optional from cpl_core.database.context import DatabaseContextABC @@ -100,9 +101,17 @@ class AuthUserRepositoryService(AuthUserRepositoryABC): ): crit_sort_direction = criteria.sort_direction.lower() if crit_sort_direction == "desc" or crit_sort_direction == "descending": - query = query.order_by_descending(lambda x: getattr(x, criteria.sort_column)) + query = query.order_by_descending( + lambda x: getattr(x, criteria.sort_column) + if not isinstance(getattr(x, criteria.sort_column), Enum) + else getattr(x, criteria.sort_column).value + ) else: - query = query.order_by(lambda x: getattr(x, criteria.sort_column)) + query = query.order_by( + lambda x: getattr(x, criteria.sort_column) + if not isinstance(getattr(x, criteria.sort_column), Enum) + else getattr(x, criteria.sort_column).value + ) result = FilteredResult() result.total_count = query.count() diff --git a/kdb-web/src/app/base/component-with-table.ts b/kdb-web/src/app/base/component-with-table.ts index 97828341..ae39c2b3 100644 --- a/kdb-web/src/app/base/component-with-table.ts +++ b/kdb-web/src/app/base/component-with-table.ts @@ -1,4 +1,4 @@ -interface Column { +export interface Column { key: string; name: string; } diff --git a/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.html b/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.html index 58f5eb9d..6699495b 100644 --- a/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.html +++ b/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.html @@ -9,11 +9,14 @@
-
- {{users.length}} {{'common.of' | translate}} - {{dt.totalRecords}} - - {{'admin.auth_users.users' | translate}} +
+
+ {{users.length}} {{'common.of' | translate}} + {{dt.totalRecords}} + + {{'admin.auth_users.users' | translate}} +
+
@@ -29,44 +32,44 @@ - +
-
{{'admin.auth_users.headers.first_name' | translate}}
+
{{'common.first_name' | translate}}
- +
-
{{'admin.auth_users.headers.last_name' | translate}}
+
{{'common.last_name' | translate}}
- +
{{'common.email' | translate}}
- +
-
{{'admin.auth_users.headers.active' | translate}}
+
{{'common.active' | translate}}
- +
-
{{'admin.auth_users.headers.role' | translate}}
+
{{'common.role' | translate}}
- +
-
{{'admin.auth_users.headers.password' | translate}}
+
{{'common.password' | translate}}
@@ -89,28 +92,28 @@ - +
- +
- +
- +
- +
- - + +
- +
- + @@ -119,7 +122,7 @@ - + - + - + - + - + - + { + it('should create an instance', () => { + expect(new HideableComponent()).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/shared/base/hideable-component.ts b/kdb-web/src/app/modules/shared/base/hideable-component.ts new file mode 100644 index 00000000..4421ff91 --- /dev/null +++ b/kdb-web/src/app/modules/shared/base/hideable-component.ts @@ -0,0 +1,13 @@ +import { Directive, HostBinding, Input } from "@angular/core"; +import { ComponentWithTable } from "../../../base/component-with-table"; + +@Directive() +export class HideableComponent { + @HostBinding("class.hidden-column") + get hidden() { + return !(this.parent?.isColumnVisible(this.column) ?? true); + }; + + @Input() column!: string; + @Input() parent!: ComponentWithTable; +} diff --git a/kdb-web/src/app/modules/shared/base/multi-select-columns/multi-select-columns.component.html b/kdb-web/src/app/modules/shared/base/multi-select-columns/multi-select-columns.component.html new file mode 100644 index 00000000..d26b948b --- /dev/null +++ b/kdb-web/src/app/modules/shared/base/multi-select-columns/multi-select-columns.component.html @@ -0,0 +1,16 @@ +
+ + +
+
+ {{'common.' + item.name | translate}}, +
+
+
{{'common.hidden_columns' | translate}}
+
+ + +
{{'common.' + item.name | translate}}
+
+
+
diff --git a/kdb-web/src/app/modules/shared/base/multi-select-columns/multi-select-columns.component.scss b/kdb-web/src/app/modules/shared/base/multi-select-columns/multi-select-columns.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/shared/base/multi-select-columns/multi-select-columns.component.spec.ts b/kdb-web/src/app/modules/shared/base/multi-select-columns/multi-select-columns.component.spec.ts new file mode 100644 index 00000000..fd671a32 --- /dev/null +++ b/kdb-web/src/app/modules/shared/base/multi-select-columns/multi-select-columns.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MultiSelectColumnsComponent } from './multi-select-columns.component'; + +describe('MultiSelectColumnsComponent', () => { + let component: MultiSelectColumnsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ MultiSelectColumnsComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(MultiSelectColumnsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/shared/base/multi-select-columns/multi-select-columns.component.ts b/kdb-web/src/app/modules/shared/base/multi-select-columns/multi-select-columns.component.ts new file mode 100644 index 00000000..db458e39 --- /dev/null +++ b/kdb-web/src/app/modules/shared/base/multi-select-columns/multi-select-columns.component.ts @@ -0,0 +1,24 @@ +import { Component, EventEmitter, Input, Output } from "@angular/core"; +import { Column } from "../../../../base/component-with-table"; + +@Component({ + selector: "app-multi-select-columns", + templateUrl: "./multi-select-columns.component.html", + styleUrls: ["./multi-select-columns.component.scss"] +}) +export class MultiSelectColumnsComponent { + @Input() columns: Column[] = []; + + private _hiddenColumns: Column[] = []; + @Input() + set hiddenColumns(columns: Column[]) { + this._hiddenColumns = columns; + this.hiddenColumnsChange.emit(columns); + } + + get hiddenColumns(): Column[] { + return this._hiddenColumns; + } + + @Output() hiddenColumnsChange: EventEmitter = new EventEmitter(); +} diff --git a/kdb-web/src/app/modules/shared/components/hideable-column/hideable-column.component.html b/kdb-web/src/app/modules/shared/components/hideable-column/hideable-column.component.html new file mode 100644 index 00000000..6dbc7430 --- /dev/null +++ b/kdb-web/src/app/modules/shared/components/hideable-column/hideable-column.component.html @@ -0,0 +1 @@ + diff --git a/kdb-web/src/app/modules/shared/components/hideable-column/hideable-column.component.scss b/kdb-web/src/app/modules/shared/components/hideable-column/hideable-column.component.scss new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/kdb-web/src/app/modules/shared/components/hideable-column/hideable-column.component.scss @@ -0,0 +1 @@ + diff --git a/kdb-web/src/app/modules/shared/components/hideable-column/hideable-column.component.spec.ts b/kdb-web/src/app/modules/shared/components/hideable-column/hideable-column.component.spec.ts new file mode 100644 index 00000000..dfa08452 --- /dev/null +++ b/kdb-web/src/app/modules/shared/components/hideable-column/hideable-column.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HideableColumnComponent } from './hideable-column.component'; + +describe('HideableColumnComponent', () => { + let component: HideableColumnComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ HideableColumnComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(HideableColumnComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/shared/components/hideable-column/hideable-column.component.ts b/kdb-web/src/app/modules/shared/components/hideable-column/hideable-column.component.ts new file mode 100644 index 00000000..4cba495c --- /dev/null +++ b/kdb-web/src/app/modules/shared/components/hideable-column/hideable-column.component.ts @@ -0,0 +1,16 @@ +import { Component, Input } from "@angular/core"; +import { HideableComponent } from "../../base/hideable-component"; + +@Component({ + selector: "[hideable-td]", + templateUrl: "./hideable-column.component.html", + styleUrls: ["./hideable-column.component.scss"] +}) +export class HideableColumnComponent extends HideableComponent { + @Input("hideable-td") override column!: string; + + constructor() { + super(); + } + +} diff --git a/kdb-web/src/app/modules/shared/components/hideable-header/hideable-header.component.html b/kdb-web/src/app/modules/shared/components/hideable-header/hideable-header.component.html new file mode 100644 index 00000000..f35a2a42 --- /dev/null +++ b/kdb-web/src/app/modules/shared/components/hideable-header/hideable-header.component.html @@ -0,0 +1,11 @@ + + + + +
+ +
+ + + + diff --git a/kdb-web/src/app/modules/shared/components/hideable-header/hideable-header.component.scss b/kdb-web/src/app/modules/shared/components/hideable-header/hideable-header.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/shared/components/hideable-header/hideable-header.component.spec.ts b/kdb-web/src/app/modules/shared/components/hideable-header/hideable-header.component.spec.ts new file mode 100644 index 00000000..27570e8b --- /dev/null +++ b/kdb-web/src/app/modules/shared/components/hideable-header/hideable-header.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HideableHeaderComponent } from './hideable-header.component'; + +describe('HideableHeaderComponent', () => { + let component: HideableHeaderComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ HideableHeaderComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(HideableHeaderComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/shared/components/hideable-header/hideable-header.component.ts b/kdb-web/src/app/modules/shared/components/hideable-header/hideable-header.component.ts new file mode 100644 index 00000000..bd7f5597 --- /dev/null +++ b/kdb-web/src/app/modules/shared/components/hideable-header/hideable-header.component.ts @@ -0,0 +1,16 @@ +import { Component, Input } from "@angular/core"; +import { HideableComponent } from "../../base/hideable-component"; + +@Component({ + selector: "[hideable-th]", + templateUrl: "./hideable-header.component.html", + styleUrls: ["./hideable-header.component.scss"] +}) +export class HideableHeaderComponent extends HideableComponent { + @Input("hideable-th") override column!: string; + @Input() sortable: boolean = false; + constructor() { + super(); + } + +} diff --git a/kdb-web/src/app/modules/shared/shared.module.ts b/kdb-web/src/app/modules/shared/shared.module.ts index 68eb5b71..ae7d2ebd 100644 --- a/kdb-web/src/app/modules/shared/shared.module.ts +++ b/kdb-web/src/app/modules/shared/shared.module.ts @@ -13,7 +13,7 @@ import { InputTextModule } from "primeng/inputtext"; import { MenuModule } from "primeng/menu"; import { PasswordModule } from "primeng/password"; import { ProgressSpinnerModule } from "primeng/progressspinner"; -import { TableModule } from "primeng/table"; +import { SortableColumn, TableModule } from "primeng/table"; import { ToastModule } from "primeng/toast"; import { AuthRolePipe } from "./pipes/auth-role.pipe"; import { IpAddressPipe } from "./pipes/ip-address.pipe"; @@ -27,6 +27,9 @@ import { HistoryBtnComponent } from "./components/history-btn/history-btn.compon import { DataViewModule, DataViewLayoutOptions } from "primeng/dataview"; import { ConfigListComponent } from "./components/config-list/config-list.component"; import { MultiSelectModule } from "primeng/multiselect"; +import { HideableColumnComponent } from './components/hideable-column/hideable-column.component'; +import { HideableHeaderComponent } from './components/hideable-header/hideable-header.component'; +import { MultiSelectColumnsComponent } from './base/multi-select-columns/multi-select-columns.component'; @NgModule({ @@ -35,7 +38,10 @@ import { MultiSelectModule } from "primeng/multiselect"; IpAddressPipe, BoolPipe, HistoryBtnComponent, - ConfigListComponent + ConfigListComponent, + HideableColumnComponent, + HideableHeaderComponent, + MultiSelectColumnsComponent, ], imports: [ CommonModule, @@ -61,7 +67,7 @@ import { MultiSelectModule } from "primeng/multiselect"; ImageModule, SidebarModule, DataViewModule, - MultiSelectModule + MultiSelectModule, ], exports: [ ButtonModule, @@ -92,7 +98,10 @@ import { MultiSelectModule } from "primeng/multiselect"; DataViewModule, DataViewLayoutOptions, ConfigListComponent, - MultiSelectModule + MultiSelectModule, + HideableColumnComponent, + HideableHeaderComponent, + MultiSelectColumnsComponent, ] }) export class SharedModule { diff --git a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html index 44f88ad5..23ea6dd2 100644 --- a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html +++ b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html @@ -9,11 +9,15 @@
-
- {{achievements.length}} {{'common.of' | translate}} - {{dt.totalRecords}} - - {{'view.server.achievements.achievements' | translate}} +
+
+ {{achievements.length}} {{'common.of' | translate}} + {{dt.totalRecords}} + + {{'view.server.achievements.achievements' | translate}} +
+ +
@@ -29,44 +33,44 @@ - +
{{'common.id' | translate}}
- +
-
{{'view.server.achievements.headers.name' | translate}}
+
{{'common.name' | translate}}
- +
-
{{'view.server.achievements.headers.description' | translate}}
+
{{'common.description' | translate}}
- +
-
{{'view.server.achievements.headers.attribute' | translate}}
+
{{'common.attribute' | translate}}
- +
-
{{'view.server.achievements.headers.operator' | translate}}
+
{{'common.operator' | translate}}
- +
-
{{'view.server.achievements.headers.value' | translate}}
+
{{'common.value' | translate}}
@@ -91,27 +95,27 @@ - +
- +
+ placeholder="{{'common.name' | translate}}">
- +
- +
- - - + + + @@ -120,7 +124,7 @@ - + {{achievement.id}} @@ -131,7 +135,7 @@ - + @@ -142,7 +146,7 @@ - + @@ -153,11 +157,11 @@ - + + placeholder="{{'common.attribute' | translate}}"> {{achievement.attribute}} @@ -165,10 +169,10 @@ - + - + {{achievement.operator}} @@ -176,7 +180,7 @@ - + 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 6a65d21c..a96d24ac 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 @@ -22,13 +22,14 @@ import { Table } from "primeng/table"; import { User } from "../../../../../../models/data/user.model"; import { AchievementMutationResult } from "../../../../../../models/graphql/result.model"; import { Mutations } from "../../../../../../models/graphql/mutations.model"; +import { ComponentWithTable } from "../../../../../../base/component-with-table"; @Component({ selector: "app-achievement", templateUrl: "./achievement.component.html", styleUrls: ["./achievement.component.scss"] }) -export class AchievementComponent implements OnInit, OnDestroy { +export class AchievementComponent extends ComponentWithTable implements OnInit, OnDestroy { public achievements: Achievement[] = []; public loading = true; @@ -37,6 +38,7 @@ export class AchievementComponent implements OnInit, OnDestroy { public filterForm!: FormGroup<{ id: FormControl, name: FormControl, + description: FormControl, color: FormControl, min_xp: FormControl, permissions: FormControl, @@ -79,6 +81,7 @@ export class AchievementComponent implements OnInit, OnDestroy { private data: DataService, private sidebar: SidebarService, private route: ActivatedRoute) { + super("achievement", ["id", "name", "description", "attribute", "operator", "value"]); } public ngOnInit(): void { @@ -157,6 +160,7 @@ export class AchievementComponent implements OnInit, OnDestroy { this.filterForm = this.fb.group({ id: new FormControl(null), name: new FormControl(null), + description: new FormControl(null), color: new FormControl(null), min_xp: new FormControl(null), permissions: new FormControl(null) diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.html b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.html index c44d7208..3b2c6864 100644 --- a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.html +++ b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.html @@ -9,11 +9,14 @@
-
- {{rules.length}} {{'common.of' | translate}} - {{dt.totalRecords}} - - {{'view.server.auto_roles.rules.auto_roles' | translate}} +
+
+ {{rules.length}} {{'common.of' | translate}} + {{dt.totalRecords}} + + {{'view.server.auto_roles.rules.auto_roles' | translate}} +
+
@@ -29,23 +32,23 @@ - +
{{'common.id' | translate}}
- +
-
{{'view.server.auto_roles.rules.headers.role' | translate}}
+
{{'common.role' | translate}}
- +
-
{{'view.server.auto_roles.rules.headers.emoji' | translate}}
+
{{'common.emoji' | translate}}
@@ -69,17 +72,17 @@ - +
- +
- +
- + @@ -88,7 +91,7 @@ - + {{autoRoleRule.id}} @@ -99,11 +102,11 @@ - + + placeholder="{{'common.role' | translate}}"> {{autoRoleRule.roleName}} @@ -111,11 +114,11 @@ - + + placeholder="{{'common.emoji' | translate}}">