From e754a10241af2d7bf995e5936961c2fcaae66797 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 13 Nov 2022 11:56:42 +0100 Subject: [PATCH] Added command checks #114 --- kdb-bot/src/bot/main.py | 2 + .../bot_core/core_extension/core_extension.py | 28 +++++++ kdb-bot/src/bot_core/exception/__init__.py | 0 kdb-bot/src/bot_core/exception/check_error.py | 7 ++ kdb-bot/src/bot_core/helper/command_checks.py | 76 +++++++++++++++++++ .../modules/base/command/restart_command.py | 14 +--- .../events/base_on_command_error_event.py | 4 + 7 files changed, 120 insertions(+), 11 deletions(-) create mode 100644 kdb-bot/src/bot_core/core_extension/core_extension.py create mode 100644 kdb-bot/src/bot_core/exception/__init__.py create mode 100644 kdb-bot/src/bot_core/exception/check_error.py create mode 100644 kdb-bot/src/bot_core/helper/command_checks.py diff --git a/kdb-bot/src/bot/main.py b/kdb-bot/src/bot/main.py index 9747634b..b5e2a6c2 100644 --- a/kdb-bot/src/bot/main.py +++ b/kdb-bot/src/bot/main.py @@ -12,6 +12,7 @@ from bot.startup_migration_extension import StartupMigrationExtension from bot.startup_module_extension import StartupModuleExtension 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.database.database_extension import DatabaseExtension @@ -31,6 +32,7 @@ class Program: .use_extension(BootLogExtension) \ .use_extension(DatabaseExtension) \ .use_extension(AppApiExtension) \ + .use_extension(CoreExtension) \ .use_startup(Startup) self.app: Application = await app_builder.build_async() await self.app.run_async() diff --git a/kdb-bot/src/bot_core/core_extension/core_extension.py b/kdb-bot/src/bot_core/core_extension/core_extension.py new file mode 100644 index 00000000..fba66dd7 --- /dev/null +++ b/kdb-bot/src/bot_core/core_extension/core_extension.py @@ -0,0 +1,28 @@ +from cpl_core.application import ApplicationExtensionABC +from cpl_core.configuration import ConfigurationABC +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_translation import TranslatePipe + +from bot_core.abc.client_utils_service_abc import ClientUtilsServiceABC +from bot_core.abc.message_service_abc import MessageServiceABC +from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum +from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings +from bot_core.helper.command_checks import CommandChecks +from modules.permission.abc.permission_service_abc import PermissionServiceABC + + +class CoreExtension(ApplicationExtensionABC): + + def __init__(self): + ApplicationExtensionABC.__init__(self) + + async def run(self, config: ConfigurationABC, services: ServiceProviderABC): + feature_flags: FeatureFlagsSettings = config.get_configuration(FeatureFlagsSettings) + if not feature_flags.get_flag(FeatureFlagsEnum.core_module): + return + + permissions: PermissionServiceABC = services.get_service(PermissionServiceABC) + client_utils: ClientUtilsServiceABC = services.get_service(ClientUtilsServiceABC) + message_service: MessageServiceABC = services.get_service(MessageServiceABC) + t: TranslatePipe = services.get_service(TranslatePipe) + CommandChecks.init(permissions, client_utils, message_service, t) diff --git a/kdb-bot/src/bot_core/exception/__init__.py b/kdb-bot/src/bot_core/exception/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/kdb-bot/src/bot_core/exception/check_error.py b/kdb-bot/src/bot_core/exception/check_error.py new file mode 100644 index 00000000..d5c9a2b8 --- /dev/null +++ b/kdb-bot/src/bot_core/exception/check_error.py @@ -0,0 +1,7 @@ +from discord.ext.commands import CommandError + + +class CheckError(CommandError): + + def __init__(self, message, *args): + CommandError.__init__(self, message, *args) diff --git a/kdb-bot/src/bot_core/helper/command_checks.py b/kdb-bot/src/bot_core/helper/command_checks.py new file mode 100644 index 00000000..6bb3fa30 --- /dev/null +++ b/kdb-bot/src/bot_core/helper/command_checks.py @@ -0,0 +1,76 @@ +from typing import Optional + +from cpl_translation import TranslatePipe +from discord.ext import commands +from discord.ext.commands import Context + +from bot_core.abc.client_utils_service_abc import ClientUtilsServiceABC +from bot_core.abc.message_service_abc import MessageServiceABC +from bot_core.exception.check_error import CheckError +from modules.permission.abc.permission_service_abc import PermissionServiceABC + + +class CommandChecks: + _permissions: Optional[PermissionServiceABC] = None + _client_utils: Optional[ClientUtilsServiceABC] = None + _message_service: Optional[MessageServiceABC] = None + _t: Optional[TranslatePipe] = None + + @classmethod + def init( + cls, + permissions: PermissionServiceABC, + client_utils: ClientUtilsServiceABC, + message_service: MessageServiceABC, + translate: TranslatePipe, + ): + cls._permissions = permissions + cls._client_utils = client_utils + cls._message_service = message_service + cls._t = translate + + @classmethod + def check_is_ready(cls): + async def check_if_bot_is_ready_yet_and_respond(ctx: Context) -> bool: + result = await cls._client_utils.check_if_bot_is_ready_yet_and_respond(ctx) + if not result: + raise CheckError(f'Bot is not ready') + return result + + return commands.check(check_if_bot_is_ready_yet_and_respond) + + @classmethod + def check_is_member_admin(cls): + async def check_is_member_admin(ctx: Context): + has_permission = cls._permissions.is_member_admin(ctx.author) + if not has_permission: + await cls._message_service.send_ctx_msg(ctx, cls._t.transform('common.no_permission_message')) + raise CheckError(f'Member {ctx.author.name} is not admin') + + return has_permission + + return commands.check(check_is_member_admin) + + @classmethod + def check_is_member_technician(cls): + async def check_is_member_technician(ctx: Context): + has_permission = cls._permissions.is_member_technician(ctx.author) + if not has_permission: + await cls._message_service.send_ctx_msg(ctx, cls._t.transform('common.no_permission_message')) + raise CheckError(f'Member {ctx.author.name} is not technician') + + return has_permission + + return commands.check(check_is_member_technician) + + @classmethod + def check_is_member_moderator(cls): + async def check_is_member_moderator(ctx: Context): + has_permission = cls._permissions.is_member_moderator(ctx.author) + if not has_permission: + await cls._message_service.send_ctx_msg(ctx, cls._t.transform('common.no_permission_message')) + raise CheckError(f'Member {ctx.author.name} is not moderator') + + return has_permission + + return commands.check(check_is_member_moderator) diff --git a/kdb-bot/src/modules/base/command/restart_command.py b/kdb-bot/src/modules/base/command/restart_command.py index 829810e0..c1fd3ae5 100644 --- a/kdb-bot/src/modules/base/command/restart_command.py +++ b/kdb-bot/src/modules/base/command/restart_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 @@ -11,6 +10,7 @@ from discord.ext.commands import Context from bot_core.abc.client_utils_service_abc import ClientUtilsServiceABC 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 @@ -43,18 +43,10 @@ class RestartCommand(DiscordCommandABC): @commands.hybrid_command() @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_moderator() async def restart(self, ctx: Context): self._logger.debug(__name__, f'Received command restart {ctx}') - if not await self._client_utils.check_if_bot_is_ready_yet_and_respond(ctx): - return - self._client_utils.received_command(ctx.guild.id) - - self._client_utils.received_command(ctx.guild.id) - - if not self._permissions.is_member_moderator(ctx.author): - await self._message_service.send_ctx_msg(ctx, self._t.transform('common.no_permission_message')) - self._logger.trace(__name__, f'Finished restart command') - return self._config.add_configuration('IS_RESTART', 'true') await self._client_utils.presence_game('common.presence.restart') 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 72a7a20e..6233d978 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 @@ -13,6 +13,7 @@ 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 class BaseOnCommandErrorEvent(OnCommandErrorABC): @@ -35,6 +36,9 @@ class BaseOnCommandErrorEvent(OnCommandErrorABC): self._t = translate async def on_command_error(self, ctx: Context, error: CommandError): + if isinstance(error, CheckError): + return + error = getattr(error, 'original', error) uid = uuid.uuid4() self._logger.error(__name__, f'Got error: {type(error).__name__} UID: {uid}')