diff --git a/src/gismo/application.py b/src/gismo/application.py index 1562d7b..8d74f08 100644 --- a/src/gismo/application.py +++ b/src/gismo/application.py @@ -5,11 +5,9 @@ from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.logging import LoggerABC from gismo_core.abc.bot_service_abc import BotServiceABC -from gismo_core.abc.module_service_abc import ModuleServiceABC from gismo_core.configuration.bot_settings import BotSettings from gismo_core.configuration.server_settings import ServerSettings from gismo_core.service.bot_service import BotService -from gismo_data.service.migration_service import MigrationService class Gismo(ApplicationABC): @@ -31,6 +29,7 @@ class Gismo(ApplicationABC): async def main(self): try: + self._logger.debug(__name__, f'Starting...\n') self._logger.trace(__name__, f'Try to start {BotService}') await self._bot.start_async() except Exception as e: diff --git a/src/gismo/startup.py b/src/gismo/startup.py index 5f64d5e..07f155e 100644 --- a/src/gismo/startup.py +++ b/src/gismo/startup.py @@ -5,15 +5,16 @@ from typing import Optional from cpl_core.application import StartupABC from cpl_core.configuration import ConfigurationABC from cpl_core.database import DatabaseSettings -from cpl_core.dependency_injection import (ServiceCollectionABC, - ServiceProviderABC) +from cpl_core.dependency_injection import ServiceCollectionABC, ServiceProviderABC from cpl_core.environment import ApplicationEnvironment from cpl_core.logging import LoggerABC from gismo_core.abc.bot_service_abc import BotServiceABC +from gismo_core.abc.client_utils_service_abc import ClientUtilsServiceABC from gismo_core.abc.command_abc import CommandABC from gismo_core.abc.message_service_abc import MessageServiceABC from gismo_core.service.bot_service import BotService +from gismo_core.service.client_utils_service import ClientUtilsService from gismo_core.service.message_service import MessageService from gismo_data.abc.known_user_repository_abc import KnownUserRepositoryABC from gismo_data.abc.migration_abc import MigrationABC @@ -36,15 +37,17 @@ from gismo_data.service.user_joined_server_repository_service import UserJoinedS from gismo_data.service.user_joined_voice_channel_service import UserJoinedVoiceChannelRepositoryService from gismo_data.service.user_repository_service import UserRepositoryService from modules.base.base import Base -from modules.base.service.base_command_service import BaseCommandService +from modules.base.service.afk_command_service import AFKCommandService +from modules.base.service.ping_command_service import PingCommandService +from modules.base.service.purge_command_service import PurgeCommandService from modules.boot_log.boot_log import BootLog from modules.database.database import Database from modules.permission.abc.permission_service_abc import PermissionServiceABC from modules.permission.permission import Permission -from modules.permission.service.permission_service import PermissionService from gismo_core.abc.module_abc import ModuleABC from gismo_core.abc.module_service_abc import ModuleServiceABC from gismo_core.service.module_service import ModuleService +from modules.permission.service.permission_service import PermissionService class Startup(StartupABC): @@ -69,6 +72,7 @@ class Startup(StartupABC): return configuration async def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: + provider: ServiceProviderABC = services.build_service_provider() services.add_logging() services.add_db_context(DBContext, self._config.get_configuration(DatabaseSettings)) @@ -78,6 +82,7 @@ class Startup(StartupABC): services.add_singleton(BotServiceABC, BotService) services.add_transient(MessageServiceABC, MessageService) services.add_transient(MigrationService) + services.add_transient(ClientUtilsServiceABC, ClientUtilsService) # data services services.add_transient(ServerRepositoryABC, ServerRepositoryService) @@ -91,7 +96,9 @@ class Startup(StartupABC): services.add_singleton(PermissionServiceABC, PermissionService) # commands - services.add_singleton(CommandABC, BaseCommandService) + services.add_singleton(CommandABC, PingCommandService) + services.add_singleton(CommandABC, PurgeCommandService) + services.add_singleton(CommandABC, AFKCommandService) # modules services.add_transient(ModuleABC, Database) @@ -104,8 +111,6 @@ class Startup(StartupABC): services.add_transient(MigrationABC, Migration_0_3) services.add_transient(MigrationABC, Migration_0_3_1) - provider: ServiceProviderABC = services.build_service_provider() - startup_init_time = round((datetime.now() - datetime.strptime(self._config.get_configuration('Startup_StartTime'), '%Y-%m-%d %H:%M:%S.%f')).total_seconds(), 2) self._config.add_configuration('Startup_InitTime', str(startup_init_time)) logger: LoggerABC = provider.get_service(LoggerABC) diff --git a/src/gismo_core/abc/client_utils_service_abc.py b/src/gismo_core/abc/client_utils_service_abc.py new file mode 100644 index 0000000..c4ac152 --- /dev/null +++ b/src/gismo_core/abc/client_utils_service_abc.py @@ -0,0 +1,13 @@ +from abc import ABC, abstractmethod + + +class ClientUtilsServiceABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + def received_command(self, guild_id: int): pass + + @abstractmethod + def moved_user(self, guild_id: int): pass diff --git a/src/gismo_core/abc/events/__init__.py b/src/gismo_core/abc/events/__init__.py new file mode 100644 index 0000000..0e1ca48 --- /dev/null +++ b/src/gismo_core/abc/events/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +gismo sh-edraft Gismo +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Dicord bot Gismo + +:copyright: (c) 2021 - 2022 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'gismo_core.abc.events' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' +__version__ = '0.4.3' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='4', micro='3') diff --git a/src/gismo_core/service/client_utils_service.py b/src/gismo_core/service/client_utils_service.py new file mode 100644 index 0000000..a3ed597 --- /dev/null +++ b/src/gismo_core/service/client_utils_service.py @@ -0,0 +1,36 @@ +from cpl_core.database.context import DatabaseContextABC + +from gismo_core.abc.bot_service_abc import BotServiceABC +from gismo_core.abc.client_utils_service_abc import ClientUtilsServiceABC +from gismo_data.abc.client_repository_abc import ClientRepositoryABC +from gismo_data.abc.server_repository_abc import ServerRepositoryABC + + +class ClientUtilsService(ClientUtilsServiceABC): + + def __init__( + self, + bot: BotServiceABC, + servers: ServerRepositoryABC, + clients: ClientRepositoryABC, + db: DatabaseContextABC + ): + ClientUtilsServiceABC.__init__(self) + self._bot = bot + self._servers = servers + self._clients = clients + self._db = db + + def received_command(self, guild_id: int): + server = self._servers.get_server_by_discord_id(guild_id) + client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.server_id) + client.received_command_count += 1 + self._clients.update_client(client) + self._db.save_changes() + + def moved_user(self, guild_id: int): + server = self._servers.get_server_by_discord_id(guild_id) + client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.server_id) + client.moved_users_count += 1 + self._clients.update_client(client) + self._db.save_changes() diff --git a/src/modules/base/base.py b/src/modules/base/base.py index b323a47..d4b9bd1 100644 --- a/src/modules/base/base.py +++ b/src/modules/base/base.py @@ -21,7 +21,9 @@ from gismo_data.model.user import User from gismo_data.model.user_joined_server import UserJoinedServer from gismo_data.model.user_joined_voice_channel import UserJoinedVoiceChannel from modules.base.base_settings import BaseSettings -from modules.base.service.base_command_service import BaseCommandService +from modules.base.service.afk_command_service import AFKCommandService +from modules.base.service.ping_command_service import PingCommandService +from modules.base.service.purge_command_service import PurgeCommandService from modules.permission.abc.permission_service_abc import PermissionServiceABC from gismo_core.abc.events.on_member_join_abc import OnMemberJoinABC from gismo_core.abc.events.on_member_remove_abc import OnMemberRemoveABC @@ -47,7 +49,9 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS db: DatabaseContextABC, messenger: MessageServiceABC, permission_service: PermissionServiceABC, - base_command_service: BaseCommandService + ping_command: PingCommandService, + purge_command: PurgeCommandService, + afk_command: AFKCommandService ): self._config = config self._logger = logger @@ -72,7 +76,11 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS }, [BaseSettings] ) - self._bot.add_cog(base_command_service) + + self._bot.add_cog(ping_command) + self._bot.add_cog(purge_command) + self._bot.add_cog(afk_command) + self._logger.info(__name__, f'Module {type(self)} loaded') def _get_config(self, g_id: int) -> BaseSettings: diff --git a/src/modules/base/service/afk_command_service.py b/src/modules/base/service/afk_command_service.py new file mode 100644 index 0000000..2499476 --- /dev/null +++ b/src/modules/base/service/afk_command_service.py @@ -0,0 +1,62 @@ +from cpl_core.configuration import ConfigurationABC +from cpl_core.database.context import DatabaseContext +from cpl_core.logging import LoggerABC +from discord import VoiceChannel +from discord.ext import commands +from discord.ext.commands import Context + +from gismo_core.abc.bot_service_abc import BotServiceABC +from gismo_core.abc.client_utils_service_abc import ClientUtilsServiceABC +from gismo_core.abc.command_abc import CommandABC +from gismo_core.abc.message_service_abc import MessageServiceABC +from gismo_core.configuration.server_settings import ServerSettings +from gismo_data.abc.client_repository_abc import ClientRepositoryABC +from modules.base.base_settings import BaseSettings + + +class AFKCommandService(CommandABC): + + def __init__( + self, + logger: LoggerABC, + config: ConfigurationABC, + message_service: MessageServiceABC, + clients: ClientRepositoryABC, + db: DatabaseContext, + bot: BotServiceABC, + client_utils: ClientUtilsServiceABC + ): + CommandABC.__init__(self) + + self._logger = logger + self._config = config + self._message_service = message_service + self._clients = clients + self._db = db + self._bot = bot + self._client_utils = client_utils + + self._logger.trace(__name__, f'Loaded command service: {type(self).__name__}') + + @commands.command() + async def afk(self, ctx: Context): + self._logger.debug(__name__, f'Received command afk {ctx}') + self._client_utils.received_command(ctx.guild.id) + settings: BaseSettings = self._config.get_configuration(f'Base_{ctx.guild.id}') + server_settings: ServerSettings = self._config.get_configuration(f'DSERVER_{ctx.guild.id}') + + if ctx.author.voice is None or ctx.author.voice.channel is None: + await self._message_service.send_ctx_msg(ctx, settings.afk_command_channel_missing_message) + self._logger.trace(__name__, f'Finished afk command') + return + + self._bot.loop.create_task(self._message_service.send_ctx_msg(ctx, settings.afk_command_move_message)) + channel: VoiceChannel = ctx.guild.get_channel(settings.afk_command_channel_id) + try: + await ctx.author.move_to(channel) + self._client_utils.moved_user(ctx.guild.id) + except Exception as e: + self._logger.error(__name__, f'Cannot move user {ctx.author.id} to channel {ctx.channel.id}', e) + await self._message_service.send_ctx_msg(ctx, server_settings.bot_has_no_permission_message) + + self._logger.trace(__name__, f'Finished afk command') diff --git a/src/modules/base/service/base_command_service.py b/src/modules/base/service/base_command_service.py deleted file mode 100644 index d33ed6e..0000000 --- a/src/modules/base/service/base_command_service.py +++ /dev/null @@ -1,95 +0,0 @@ -import asyncio -from cpl_core.database.context.database_context import DatabaseContext -import discord -from discord.channel import VoiceChannel -from discord.ext import commands -from discord.ext.commands import Context - -from cpl_core.logging import LoggerABC -from cpl_core.configuration import ConfigurationABC -from gismo_core.abc.bot_service_abc import BotServiceABC - -from gismo_core.abc.command_abc import CommandABC -from gismo_core.abc.message_service_abc import MessageServiceABC -from gismo_core.configuration.server_settings import ServerSettings -from gismo_data.abc.client_repository_abc import ClientRepositoryABC -from modules.base.base_settings import BaseSettings -from modules.permission.abc.permission_service_abc import PermissionServiceABC - - -class BaseCommandService(CommandABC): - - def __init__( - self, - logger: LoggerABC, - config: ConfigurationABC, - message_service: MessageServiceABC, - permissions: PermissionServiceABC, - clients: ClientRepositoryABC, - db: DatabaseContext, - bot: BotServiceABC - ): - CommandABC.__init__(self) - - self._logger = logger - self._config = config - self._message_service = message_service - self._permissions = permissions - self._clients = clients - self._db = db - self._bot = bot - - self._logger.trace(__name__, f'Loaded command service: {type(self).__name__}') - - @commands.command() - async def ping(self, ctx: Context): - self._logger.debug(__name__, f'Received command ping {ctx}') - await self._message_service.send_ctx_msg(ctx, 'Pong') - self._logger.trace(__name__, f'Finished ping command') - - @commands.command() - async def purge(self, ctx: Context): - self._logger.debug(__name__, f'Received command purge {ctx}') - settings: BaseSettings = self._config.get_configuration(f'Base_{ctx.guild.id}') - server_settings: ServerSettings = self._config.get_configuration(f'DSERVER_{ctx.guild.id}') - - if not self._permissions.is_member_moderator(ctx.author): - await self._message_service.send_ctx_msg(ctx, settings.no_permissions_message) - self._logger.trace(__name__, f'Finished purge command') - return - - await self._message_service.send_ctx_msg(ctx, settings.purge_message) - await asyncio.sleep(server_settings.message_delete_timer) - try: - await ctx.channel.purge() - except Exception as e: - self._logger.error(__name__, f'Cannot purge channel {ctx.channel.id}', e) - await self._message_service.send_ctx_msg(ctx, server_settings.bot_has_no_permission_message) - - self._logger.trace(__name__, f'Finished purge command') - - @commands.command() - async def afk(self, ctx: Context): - self._logger.debug(__name__, f'Received command afk {ctx}') - settings: BaseSettings = self._config.get_configuration(f'Base_{ctx.guild.id}') - server_settings: ServerSettings = self._config.get_configuration(f'DSERVER_{ctx.guild.id}') - - if ctx.author.voice is None or ctx.author.voice.channel is None: - await self._message_service.send_ctx_msg(ctx, settings.afk_command_channel_missing_message) - self._logger.trace(__name__, f'Finished afk command') - return - - self._bot.loop.create_task(self._message_service.send_ctx_msg(ctx, settings.afk_command_move_message)) - channel: VoiceChannel = ctx.guild.get_channel(settings.afk_command_channel_id) - try: - await ctx.author.move_to(channel) - - client = self._clients.get_client_by_discord_id(self._bot.user.id) - client.moved_users_count += 1 - self._clients.update_client(client) - self._db.save_changes() - except Exception as e: - self._logger.error(__name__, f'Cannot move user {ctx.author.id} to channel {ctx.channel.id}', e) - await self._message_service.send_ctx_msg(ctx, server_settings.bot_has_no_permission_message) - - self._logger.trace(__name__, f'Finished afk command') diff --git a/src/modules/base/service/ping_command_service.py b/src/modules/base/service/ping_command_service.py new file mode 100644 index 0000000..e13df56 --- /dev/null +++ b/src/modules/base/service/ping_command_service.py @@ -0,0 +1,34 @@ +from cpl_core.logging import LoggerABC +from discord.ext import commands +from discord.ext.commands import Context + +from gismo_core.abc.bot_service_abc import BotServiceABC +from gismo_core.abc.client_utils_service_abc import ClientUtilsServiceABC +from gismo_core.abc.command_abc import CommandABC +from gismo_core.abc.message_service_abc import MessageServiceABC + + +class PingCommandService(CommandABC): + + def __init__( + self, + logger: LoggerABC, + message_service: MessageServiceABC, + bot: BotServiceABC, + client_utils: ClientUtilsServiceABC + ): + CommandABC.__init__(self) + + self._logger = logger + self._message_service = message_service + self._bot = bot + self._client_utils = client_utils + + self._logger.trace(__name__, f'Loaded command service: {type(self).__name__}') + + @commands.command() + async def ping(self, ctx: Context): + self._logger.debug(__name__, f'Received command ping {ctx}') + self._client_utils.received_command(ctx.guild.id) + await self._message_service.send_ctx_msg(ctx, 'Pong') + self._logger.trace(__name__, f'Finished ping command') diff --git a/src/modules/base/service/purge_command_service.py b/src/modules/base/service/purge_command_service.py new file mode 100644 index 0000000..76cf34b --- /dev/null +++ b/src/modules/base/service/purge_command_service.py @@ -0,0 +1,57 @@ +import asyncio + +from cpl_core.configuration import ConfigurationABC +from cpl_core.logging import LoggerABC +from discord.ext import commands +from discord.ext.commands import Context + +from gismo_core.abc.client_utils_service_abc import ClientUtilsServiceABC +from gismo_core.abc.command_abc import CommandABC +from gismo_core.abc.message_service_abc import MessageServiceABC +from gismo_core.configuration.server_settings import ServerSettings +from modules.base.base_settings import BaseSettings +from modules.permission.abc.permission_service_abc import PermissionServiceABC + + +class PurgeCommandService(CommandABC): + + def __init__( + self, + logger: LoggerABC, + config: ConfigurationABC, + message_service: MessageServiceABC, + permissions: PermissionServiceABC, + client_utils: ClientUtilsServiceABC + ): + CommandABC.__init__(self) + + self._logger = logger + self._config = config + self._message_service = message_service + self._permissions = permissions + self._client_utils = client_utils + + self._logger.trace(__name__, f'Loaded command service: {type(self).__name__}') + + @commands.command() + async def purge(self, ctx: Context): + self._logger.debug(__name__, f'Received command purge {ctx}') + self._client_utils.received_command(ctx.guild.id) + + settings: BaseSettings = self._config.get_configuration(f'Base_{ctx.guild.id}') + server_settings: ServerSettings = self._config.get_configuration(f'DSERVER_{ctx.guild.id}') + + if not self._permissions.is_member_moderator(ctx.author): + await self._message_service.send_ctx_msg(ctx, settings.no_permissions_message) + self._logger.trace(__name__, f'Finished purge command') + return + + await self._message_service.send_ctx_msg(ctx, settings.purge_message) + await asyncio.sleep(server_settings.message_delete_timer) + try: + await ctx.channel.purge() + except Exception as e: + self._logger.error(__name__, f'Cannot purge channel {ctx.channel.id}', e) + await self._message_service.send_ctx_msg(ctx, server_settings.bot_has_no_permission_message) + + self._logger.trace(__name__, f'Finished purge command')