[WIP] Added basic commands & functionality of Gismo@0.4.10
This commit is contained in:
		| @@ -4,8 +4,18 @@ | ||||
|     "Projects": { | ||||
|       "bot": "src/bot/bot.json", | ||||
|       "bot-core": "src/bot_core/bot-core.json", | ||||
|       "bot-data": "src/bot_data/bot-data.json" | ||||
|       "bot-data": "src/bot_data/bot-data.json", | ||||
|       "database": "src/modules/database/database.json", | ||||
|       "base": "src/modules/base/base.json", | ||||
|       "permission": "src/modules/permission/permission.json", | ||||
|       "boot-log": "src/modules/boot_log/boot-log.json" | ||||
|     }, | ||||
|     "Scripts": {} | ||||
|     "Scripts": { | ||||
|       "ba": "cpl build-all", | ||||
|       "build-all": "cpl build-bot; cpl build-bot-core; cpl build-bot-data;", | ||||
|       "build-bot": "echo 'Build bot'; cd ./src/bot; cpl build; cd ../../;", | ||||
|       "build-bot-core": "echo 'Build bot-core'; cd ./src/bot_core; cpl build; cd ../../;", | ||||
|       "build-bot-data": "echo 'Build bot-data'; cd ./src/bot_data; cpl build; cd ../../;" | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -1 +1,26 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
|  | ||||
| """ | ||||
| bot Keksdose bot | ||||
| ~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| Discord bot  for the Keksdose discord Server | ||||
|  | ||||
| :copyright: (c) 2022 sh-edraft.de | ||||
| :license: MIT, see LICENSE for more details. | ||||
|  | ||||
| """ | ||||
|  | ||||
| __title__ = 'bot' | ||||
| __author__ = 'Sven Heidemann' | ||||
| __license__ = 'MIT' | ||||
| __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||
| __version__ = '1.0.0.dev1' | ||||
|  | ||||
| from collections import namedtuple | ||||
|  | ||||
|  | ||||
| # imports:  | ||||
|  | ||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||
| version_info = VersionInfo(major='1', minor='0', micro='0.dev1') | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| from cpl_core.configuration import ConfigurationABC | ||||
| from typing import Optional, Type | ||||
|  | ||||
| from cpl_core.configuration import ConfigurationABC, ConfigurationModelABC | ||||
| from cpl_core.console import Console | ||||
| from cpl_core.dependency_injection import ServiceProviderABC | ||||
| from cpl_core.logging import LoggerABC | ||||
| @@ -7,6 +9,15 @@ from cpl_discord.configuration import DiscordBotSettings | ||||
| from cpl_discord.service import DiscordBotServiceABC, DiscordBotService | ||||
| from cpl_translation import TranslatePipe, TranslationServiceABC, TranslationSettings | ||||
|  | ||||
| from bot_core.configuration.bot_settings import BotSettings | ||||
| from bot_core.configuration.server_settings import ServerSettings | ||||
| from modules.base.configuration.base_server_settings import BaseServerSettings | ||||
| from modules.base.configuration.base_settings import BaseSettings | ||||
| from modules.boot_log.configuration.boot_log_server_settings import BootLogServerSettings | ||||
| from modules.boot_log.configuration.boot_log_settings import BootLogSettings | ||||
| from modules.permission.configuration.permission_server_settings import PermissionServerSettings | ||||
| from modules.permission.configuration.permission_settings import PermissionSettings | ||||
|  | ||||
|  | ||||
| class Application(DiscordBotApplicationABC): | ||||
|  | ||||
| @@ -22,8 +33,21 @@ class Application(DiscordBotApplicationABC): | ||||
|         self._translation: TranslationServiceABC = services.get_service(TranslationServiceABC) | ||||
|         self._translate: TranslatePipe = services.get_service(TranslatePipe) | ||||
|  | ||||
|     def _configure_settings_with_servers(self, settings: Type, server_settings: Type): | ||||
|         settings: Optional[settings] = self._configuration.get_configuration(settings) | ||||
|         if settings is None: | ||||
|             return | ||||
|  | ||||
|         for server in settings.servers: | ||||
|             self._logger.trace(__name__, f'Saved config: {type(server).__name__}_{server.id}') | ||||
|             self._configuration.add_configuration(f'{type(server).__name__}_{server.id}', server) | ||||
|  | ||||
|     async def configure(self): | ||||
|         self._translation.load_by_settings(self._configuration.get_configuration(TranslationSettings)) | ||||
|         self._configure_settings_with_servers(BotSettings, ServerSettings) | ||||
|         self._configure_settings_with_servers(BaseSettings, BaseServerSettings) | ||||
|         self._configure_settings_with_servers(BootLogSettings, BootLogServerSettings) | ||||
|         self._configure_settings_with_servers(PermissionSettings, PermissionServerSettings) | ||||
|  | ||||
|     async def main(self): | ||||
|         try: | ||||
|   | ||||
| @@ -17,7 +17,7 @@ | ||||
|     "LicenseDescription": "MIT, see LICENSE for more details.", | ||||
|     "Dependencies": [ | ||||
|       "cpl-core>=2022.7.0.post1", | ||||
|       "cpl-translation==2022.7.0.post1", | ||||
|       "cpl-translation==2022.7.0.post2", | ||||
|       "cpl-query==2022.7.0", | ||||
|       "cpl-discord==2022.7.0.post1" | ||||
|     ], | ||||
|   | ||||
| @@ -20,14 +20,5 @@ | ||||
|   "DiscordBot": { | ||||
|     "Token": "OTA5ODc4NDcyNzExNzU3ODQ1.YZKsXA.8p-g1c37EBZzYYW09Fvr7egQzhE", | ||||
|     "Prefix": "!kd " | ||||
|   }, | ||||
|   "Bot": { | ||||
|     "Servers": [ | ||||
|       { | ||||
|         "Id": "910199451145076828", | ||||
|         "MessageDeleteTimer": 2, | ||||
|         "BotHasNoPermissionMessage": "Ich habe keine Berechtigungen :(" | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| } | ||||
| @@ -7,9 +7,9 @@ | ||||
|   }, | ||||
|   "DatabaseSettings": { | ||||
|     "Host": "localhost", | ||||
|         "User": "sh_gismo", | ||||
|         "Password": "c2hfZ2lzbW8=", | ||||
|         "Database": "sh_gismo_dev", | ||||
|     "User": "kd_kdb", | ||||
|     "Password": "VGpZcihrb0N2T2MyZUlURQ==", | ||||
|     "Database": "keksdose_bot_dev", | ||||
|     "Charset": "utf8mb4", | ||||
|     "UseUnicode": "true", | ||||
|     "Buffered": "true", | ||||
| @@ -20,12 +20,39 @@ | ||||
|     "Prefix": "!kde " | ||||
|   }, | ||||
|   "Bot": { | ||||
|         "Servers": [ | ||||
|             { | ||||
|                 "Id": "910199451145076828", | ||||
|                 "MessageDeleteTimer": 2, | ||||
|                 "BotHasNoPermissionMessage": "Ich habe keine Berechtigungen :(" | ||||
|     "511824600884051979": { | ||||
|       "MessageDeleteTimer": 2 | ||||
|     }, | ||||
|     "910199451145076828": { | ||||
|       "MessageDeleteTimer": 2 | ||||
|     } | ||||
|   }, | ||||
|   "Base": { | ||||
|     "910199451145076828": { | ||||
|       "MaxVoiceStateHours": 24, | ||||
|       "XpPerMessage": 2, | ||||
|       "XpPerOntimeHour": 4, | ||||
|       "AFKChannelIds": [ | ||||
|         910199452915093593, | ||||
|         910199452915093594 | ||||
|       ], | ||||
|       "AFKCommandChannelId": 910199452915093594, | ||||
|       "HelpCommandReferenceUrl": "https://git.sh-edraft.de/sh-edraft.de/sh_gismo/wiki/Befehle" | ||||
|     } | ||||
|   }, | ||||
|   "BootLog": { | ||||
|     "910199451145076828": { | ||||
|       "LoginMessageChannelId": "910199452915093588" | ||||
|     } | ||||
|   }, | ||||
|   "Permission": { | ||||
|     "910199451145076828": { | ||||
|       "AdminRoleIds": [ | ||||
|         925072155203477584 | ||||
|       ], | ||||
|       "ModeratorRoleIds": [ | ||||
|         925072209884635167 | ||||
|       ] | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -19,15 +19,5 @@ | ||||
|   }, | ||||
|   "Discord": { | ||||
|     "Token": "OTEwMjAxNjA1NDkwNjEwMjA3.YZPZTQ.lUj2Bs5pQAv4AJ_tb_mHMTpIRls" | ||||
|   }, | ||||
|   "Bot": { | ||||
|     "Prefix": "!kt ", | ||||
|     "Servers": [ | ||||
|       { | ||||
|         "Id": "910199451145076828", | ||||
|         "MessageDeleteTimer": 2, | ||||
|         "BotHasNoPermissionMessage": "Ich habe keine Berechtigungen :(" | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| } | ||||
| @@ -5,6 +5,10 @@ from cpl_core.application import ApplicationBuilder | ||||
|  | ||||
| from bot.application import Application | ||||
| from bot.startup import Startup | ||||
| from bot.startup_discord_extension import StartupDiscordExtension | ||||
| from bot.startup_migration_extension import StartupMigrationExtension | ||||
| from modules.boot_log.boot_log_extension import BootLogExtension | ||||
| from modules.database.database_extension import DatabaseExtension | ||||
|  | ||||
|  | ||||
| class Main: | ||||
| @@ -14,6 +18,10 @@ class Main: | ||||
|  | ||||
|     async def main(self): | ||||
|         app_builder = ApplicationBuilder(Application) | ||||
|         app_builder.use_extension(StartupDiscordExtension) | ||||
|         app_builder.use_extension(StartupMigrationExtension) | ||||
|         app_builder.use_extension(BootLogExtension) | ||||
|         app_builder.use_extension(DatabaseExtension) | ||||
|         app_builder.use_startup(Startup) | ||||
|         self._app: Application = await app_builder.build_async() | ||||
|         await self._app.run_async() | ||||
|   | ||||
| @@ -4,9 +4,31 @@ 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 ServiceProviderABC, ServiceCollectionABC | ||||
| from cpl_core.environment import ApplicationEnvironment | ||||
| from cpl_discord import get_discord_collection | ||||
|  | ||||
| from bot_core.abc.client_utils_service_abc import ClientUtilsServiceABC | ||||
| from bot_core.abc.message_service_abc import MessageServiceABC | ||||
| from bot_core.service.client_utils_service import ClientUtilsService | ||||
| from bot_core.service.message_service import MessageService | ||||
| from bot_data.abc.client_repository_abc import ClientRepositoryABC | ||||
| from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC | ||||
| 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_joined_voice_channel_abc import UserJoinedVoiceChannelRepositoryABC | ||||
| from bot_data.abc.user_repository_abc import UserRepositoryABC | ||||
| from bot_data.db_context import DBContext | ||||
| from bot_data.service.client_repository_service import ClientRepositoryService | ||||
| from bot_data.service.known_user_repository_service import KnownUserRepositoryService | ||||
| from bot_data.service.server_repository_service import ServerRepositoryService | ||||
| from bot_data.service.user_joined_server_repository_service import UserJoinedServerRepositoryService | ||||
| from bot_data.service.user_joined_voice_channel_service import UserJoinedVoiceChannelRepositoryService | ||||
| from bot_data.service.user_repository_service import UserRepositoryService | ||||
| from modules.base.abc.base_helper_abc import BaseHelperABC | ||||
| from modules.base.service.base_helper_service import BaseHelperService | ||||
| from modules.permission.abc.permission_service_abc import PermissionServiceABC | ||||
| from modules.permission.service.permission_service import PermissionService | ||||
|  | ||||
|  | ||||
| class Startup(StartupABC): | ||||
| @@ -34,7 +56,23 @@ class Startup(StartupABC): | ||||
|     def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: | ||||
|         services.add_logging() | ||||
|         services.add_translation() | ||||
|         services.add_discord() | ||||
|         discord_collection = get_discord_collection(services) | ||||
|  | ||||
|         services.add_db_context(DBContext, self._config.get_configuration(DatabaseSettings)) | ||||
|  | ||||
|         # general services | ||||
|         services.add_transient(BaseHelperABC, BaseHelperService) | ||||
|         services.add_transient(MessageServiceABC, MessageService) | ||||
|         services.add_transient(ClientUtilsServiceABC, ClientUtilsService) | ||||
|  | ||||
|         # module services | ||||
|         services.add_singleton(PermissionServiceABC, PermissionService) | ||||
|  | ||||
|         # data services | ||||
|         services.add_transient(ServerRepositoryABC, ServerRepositoryService) | ||||
|         services.add_transient(UserRepositoryABC, UserRepositoryService) | ||||
|         services.add_transient(ClientRepositoryABC, ClientRepositoryService) | ||||
|         services.add_transient(KnownUserRepositoryABC, KnownUserRepositoryService) | ||||
|         services.add_transient(UserJoinedServerRepositoryABC, UserJoinedServerRepositoryService) | ||||
|         services.add_transient(UserJoinedVoiceChannelRepositoryABC, UserJoinedVoiceChannelRepositoryService) | ||||
|  | ||||
|         return services.build_service_provider() | ||||
|   | ||||
							
								
								
									
										52
									
								
								src/bot/startup_discord_extension.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/bot/startup_discord_extension.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| from cpl_core.application import StartupExtensionABC | ||||
| from cpl_core.configuration import ConfigurationABC | ||||
| from cpl_core.dependency_injection import ServiceCollectionABC | ||||
| from cpl_core.environment import ApplicationEnvironmentABC | ||||
| from cpl_discord import get_discord_collection | ||||
| from cpl_discord.discord_event_types_enum import DiscordEventTypesEnum | ||||
|  | ||||
| from modules.base.command.afk_command import AFKCommand | ||||
| from modules.base.command.help_command import HelpCommand | ||||
| from modules.base.command.ping_command import PingCommand | ||||
| from modules.base.command.purge_command import PurgeCommand | ||||
| from modules.base.events.base_on_member_join_event import BaseOnMemberJoinEvent | ||||
| from modules.base.events.base_on_member_remove_event import BaseOnMemberRemoveEvent | ||||
| from modules.base.events.base_on_message_event import BaseOnMessageEvent | ||||
| from modules.base.events.base_on_voice_state_update_event import BaseOnVoiceStateUpdateEvent | ||||
| from modules.boot_log.boot_log_on_ready_event import BootLogOnReadyEvent | ||||
| from modules.database.database_on_ready_event import DatabaseOnReadyEvent | ||||
| from modules.permission.events.permission_on_member_update_event import PermissionOnMemberUpdateEvent | ||||
| from modules.permission.events.permission_on_ready_event import PermissionOnReadyEvent | ||||
|  | ||||
|  | ||||
| class StartupDiscordExtension(StartupExtensionABC): | ||||
|  | ||||
|     def __init__(self): | ||||
|         pass | ||||
|  | ||||
|     def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC): | ||||
|         pass | ||||
|  | ||||
|     def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): | ||||
|         services.add_discord() | ||||
|         dc = get_discord_collection(services) | ||||
|         """ commands """ | ||||
|         dc.add_command(AFKCommand) | ||||
|         dc.add_command(HelpCommand) | ||||
|         dc.add_command(PingCommand) | ||||
|         dc.add_command(PurgeCommand) | ||||
|         """ events """ | ||||
|         # on_member_join | ||||
|         dc.add_event(DiscordEventTypesEnum.on_member_join.value, BaseOnMemberJoinEvent) | ||||
|         # on_member_remove | ||||
|         dc.add_event(DiscordEventTypesEnum.on_member_join.value, BaseOnMemberRemoveEvent) | ||||
|         # on_member_update | ||||
|         dc.add_event(DiscordEventTypesEnum.on_member_update.value, PermissionOnMemberUpdateEvent) | ||||
|         # on_message | ||||
|         dc.add_event(DiscordEventTypesEnum.on_message.value, BaseOnMessageEvent) | ||||
|         # on_voice_state_update | ||||
|         dc.add_event(DiscordEventTypesEnum.on_member_join.value, BaseOnVoiceStateUpdateEvent) | ||||
|         # on_ready | ||||
|         dc.add_event(DiscordEventTypesEnum.on_ready.value, DatabaseOnReadyEvent) | ||||
|         dc.add_event(DiscordEventTypesEnum.on_ready.value, PermissionOnReadyEvent) | ||||
|         dc.add_event(DiscordEventTypesEnum.on_ready.value, BootLogOnReadyEvent)  # has to be last | ||||
							
								
								
									
										21
									
								
								src/bot/startup_migration_extension.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/bot/startup_migration_extension.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| from cpl_core.application import StartupExtensionABC | ||||
| from cpl_core.configuration import ConfigurationABC | ||||
| 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.initial_migration import InitialMigration | ||||
| from bot_data.service.migration_service import MigrationService | ||||
|  | ||||
|  | ||||
| class StartupMigrationExtension(StartupExtensionABC): | ||||
|  | ||||
|     def __init__(self): | ||||
|         pass | ||||
|  | ||||
|     def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC): | ||||
|         pass | ||||
|  | ||||
|     def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): | ||||
|         services.add_transient(MigrationService) | ||||
|         services.add_transient(MigrationABC, InitialMigration) | ||||
| @@ -1,8 +1,23 @@ | ||||
| { | ||||
|   "common": { | ||||
|     "hello-world": "Hallo Welt" | ||||
|     "hello_world": "Hallo Welt", | ||||
|     "bot_has_no_permission_message": "Ey!!!\nWas soll das?\nIch habe keine Berechtigungen :(\nScheiß System...", | ||||
|     "no_permission_message": "Nein!\nIch höre nicht auf dich ¯\\_(ツ)_/¯" | ||||
|   }, | ||||
|   "commands": { | ||||
|  | ||||
|   "modules": { | ||||
|     "base": { | ||||
|       "welcome_message": "Hello There!\nIch bin Gismo und heiße dich bei {} herzlichst willkommen!", | ||||
|       "welcome_message_for_team": "{} hat gerade das Irrenhaus betreten.", | ||||
|       "goodbye_message": "Schade das du uns so schnell verlässt :(", | ||||
|       "purge_message": "Na gut..., ich lösche alle Nachrichten wenns sein muss.", | ||||
|       "afk_command_channel_missing_message": "Zu unfähig einem Sprachkanal beizutreten?", | ||||
|       "afk_command_move_message": "Ich verschiebe dich ja schon... (◔_◔)", | ||||
|       "pong": "Pong" | ||||
|     }, | ||||
|     "boot_log": { | ||||
|       "login_message": "Ich bin on the line :D\nDer Scheiß hat {} Sekunden gedauert" | ||||
|     }, | ||||
|     "database": {}, | ||||
|     "permission": {} | ||||
|   } | ||||
| } | ||||
| @@ -1 +1,26 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
|  | ||||
| """ | ||||
| bot-core Keksdose bot - core | ||||
| ~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| Discord bot  for the Keksdose discord Server - core package | ||||
|  | ||||
| :copyright: (c) 2022 sh-edraft.de | ||||
| :license: MIT, see LICENSE for more details. | ||||
|  | ||||
| """ | ||||
|  | ||||
| __title__ = 'bot_core' | ||||
| __author__ = 'Sven Heidemann' | ||||
| __license__ = 'MIT' | ||||
| __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||
| __version__ = '1.0.0.dev1' | ||||
|  | ||||
| from collections import namedtuple | ||||
|  | ||||
|  | ||||
| # imports:  | ||||
|  | ||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||
| version_info = VersionInfo(major='1', minor='0', micro='0.dev1') | ||||
|   | ||||
							
								
								
									
										0
									
								
								src/bot_core/abc/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/bot_core/abc/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										16
									
								
								src/bot_core/abc/client_utils_service_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/bot_core/abc/client_utils_service_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| 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 | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_client(self, dc_ic: int, guild_id: int): pass | ||||
							
								
								
									
										27
									
								
								src/bot_core/abc/message_service_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/bot_core/abc/message_service_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| from abc import ABC, abstractmethod | ||||
| from typing import Union | ||||
|  | ||||
| import discord | ||||
| from cpl_query.extension import List | ||||
| from discord.ext.commands import Context | ||||
|  | ||||
|  | ||||
| class MessageServiceABC(ABC): | ||||
|  | ||||
|     @abstractmethod | ||||
|     def __init__(self): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     async def delete_messages(self, messages: List[discord.Message], guild_id: int): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     async def delete_message(self, message: discord.Message): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     async def send_channel_message(self, channel: discord.TextChannel, message: Union[str, discord.Embed]): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     async def send_dm_message(self, message: Union[str, discord.Embed], receiver: Union[discord.User, discord.Member]): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     async def send_ctx_msg(self, ctx: Context, message: Union[str, discord.Embed], file: discord.File = None, is_persistent: bool = False, wait_before_delete: int = None): pass | ||||
							
								
								
									
										0
									
								
								src/bot_core/configuration/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/bot_core/configuration/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										32
									
								
								src/bot_core/configuration/bot_settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/bot_core/configuration/bot_settings.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| import traceback | ||||
|  | ||||
| from cpl_core.configuration import ConfigurationModelABC | ||||
| from cpl_core.console import Console | ||||
| from cpl_query.extension import List | ||||
|  | ||||
| from bot_core.configuration.server_settings import ServerSettings | ||||
|  | ||||
|  | ||||
| class BotSettings(ConfigurationModelABC): | ||||
|  | ||||
|     def __init__(self): | ||||
|         ConfigurationModelABC.__init__(self) | ||||
|  | ||||
|         self._servers: List[ServerSettings] = List() | ||||
|      | ||||
|     @property | ||||
|     def servers(self) -> List[ServerSettings]: | ||||
|         return self._servers | ||||
|  | ||||
|     def from_dict(self, settings: dict): | ||||
|         try: | ||||
|             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()}') | ||||
							
								
								
									
										29
									
								
								src/bot_core/configuration/server_settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/bot_core/configuration/server_settings.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| import traceback | ||||
|  | ||||
| from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC | ||||
| from cpl_core.console import Console | ||||
|  | ||||
|  | ||||
| class ServerSettings(ConfigurationModelABC): | ||||
|  | ||||
|     def __init__(self): | ||||
|         ConfigurationModelABC.__init__(self) | ||||
|  | ||||
|         self._id: int = 0 | ||||
|         self._message_delete_timer: int = 0 | ||||
|  | ||||
|     @property | ||||
|     def id(self) -> int: | ||||
|         return self._id | ||||
|  | ||||
|     @property | ||||
|     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()}') | ||||
							
								
								
									
										0
									
								
								src/bot_core/service/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/bot_core/service/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										42
									
								
								src/bot_core/service/client_utils_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/bot_core/service/client_utils_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| from cpl_core.database.context import DatabaseContextABC | ||||
|  | ||||
| from cpl_discord.service import DiscordBotServiceABC | ||||
|  | ||||
| from bot_core.abc.client_utils_service_abc import ClientUtilsServiceABC | ||||
| from bot_data.abc.client_repository_abc import ClientRepositoryABC | ||||
| from bot_data.abc.server_repository_abc import ServerRepositoryABC | ||||
|  | ||||
|  | ||||
| class ClientUtilsService(ClientUtilsServiceABC): | ||||
|  | ||||
|     def __init__( | ||||
|             self, | ||||
|             bot: DiscordBotServiceABC, | ||||
|             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() | ||||
|  | ||||
|     def get_client(self, dc_ic: int, 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) | ||||
|         return client | ||||
							
								
								
									
										105
									
								
								src/bot_core/service/message_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/bot_core/service/message_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| import asyncio | ||||
| from typing import Union | ||||
|  | ||||
| import discord | ||||
| from cpl_core.configuration.configuration_abc import ConfigurationABC | ||||
| from cpl_core.database.context.database_context_abc import DatabaseContextABC | ||||
| from cpl_core.logging import LoggerABC | ||||
| from cpl_discord.service import DiscordBotServiceABC | ||||
| from cpl_query.extension import List | ||||
| 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_data.abc.client_repository_abc import ClientRepositoryABC | ||||
|  | ||||
|  | ||||
| class MessageService(MessageServiceABC): | ||||
|  | ||||
|     def __init__(self, config: ConfigurationABC, logger: LoggerABC, bot: DiscordBotServiceABC, clients: ClientRepositoryABC, db: DatabaseContextABC): | ||||
|         self._config = config | ||||
|         self._logger = logger | ||||
|         self._bot = bot | ||||
|         self._clients = clients | ||||
|         self._db = db | ||||
|      | ||||
|     async def delete_messages(self, messages: List[discord.Message], guild_id: int): | ||||
|         self._logger.debug(__name__, f'Try to delete {messages.count()} messages') | ||||
|         server_st: ServerSettings = self._config.get_configuration(f'ServerSettings_{guild_id}') | ||||
|         await asyncio.sleep(server_st.message_delete_timer) | ||||
|         for message in messages: | ||||
|             await self.delete_message(message, mass_delete=True) | ||||
|         self._logger.debug(__name__, 'Deleting messages finished') | ||||
|          | ||||
|     async def delete_message(self, message: discord.Message, mass_delete=False): | ||||
|         server_st: ServerSettings = self._config.get_configuration(f'ServerSettings_{message.guild.id}') | ||||
|         if not mass_delete: | ||||
|             await asyncio.sleep(server_st.message_delete_timer) | ||||
|         self._logger.debug(__name__, f'Try to delete message:\n\t{message}\n\t{message.content}') | ||||
|         guild_id = message.guild.id | ||||
|         try: | ||||
|             await message.delete() | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f'Deleting message failed', e) | ||||
|         else: | ||||
|             self._clients.append_deleted_message_count(self._bot.user.id, guild_id, 1) | ||||
|             self._db.save_changes() | ||||
|             self._logger.info(__name__, f'Deleted message {message}') | ||||
|      | ||||
|     async def send_channel_message(self, channel: discord.TextChannel, message: Union[str, discord.Embed]): | ||||
|         self._logger.debug(__name__, f'Try to send message\n\t{message}\n\tto: {channel}') | ||||
|         msg = None | ||||
|         try: | ||||
|             if isinstance(message, discord.Embed): | ||||
|                 msg = await channel.send(embed=message) | ||||
|             else: | ||||
|                 msg = await channel.send(message) | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f'Send message to channel {channel.id} failed', e) | ||||
|         else: | ||||
|             self._logger.info(__name__, f'Sent message to channel {channel.id}') | ||||
|             self._clients.append_sent_message_count(self._bot.user.id, channel.guild.id, 1) | ||||
|             self._db.save_changes() | ||||
|             await self.delete_message(msg) | ||||
|      | ||||
|     async def send_dm_message(self, message: Union[str, discord.Embed], receiver: Union[discord.User, discord.Member]): | ||||
|         self._logger.debug(__name__, f'Try to send message\n\t{message}\n\tto: {receiver}') | ||||
|         try: | ||||
|             if isinstance(message, discord.Embed): | ||||
|                 msg = await receiver.send(embed=message) | ||||
|             else: | ||||
|                 msg = await receiver.send(message) | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f'Send message to user {receiver.id} failed', e) | ||||
|         else: | ||||
|             self._clients.append_sent_message_count(self._bot.user.id, receiver.guild.id, 1) | ||||
|             self._db.save_changes() | ||||
|             self._logger.info(__name__, f'Sent message to user {receiver.id}') | ||||
|      | ||||
|     async def send_ctx_msg(self, ctx: Context, message: Union[str, discord.Embed], file: discord.File = None, is_persistent: bool = False, wait_before_delete: int = None): | ||||
|         if ctx is None: | ||||
|             self._logger.warn(__name__, 'Message context is empty') | ||||
|             self._logger.debug(__name__, f'Message: {message}') | ||||
|             return | ||||
|          | ||||
|         self._logger.debug(__name__, f'Try to send message\t\t{message}\n\tto: {ctx.channel}') | ||||
|         msg = None | ||||
|         try: | ||||
|             if isinstance(message, discord.Embed): | ||||
|                 msg = await ctx.send(embed=message, file=file) | ||||
|             else: | ||||
|                 msg = await ctx.send(message, file=file) | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f'Send message to channel {ctx.channel.id} failed', e) | ||||
|         else: | ||||
|             self._logger.info(__name__, f'Sent message to channel {ctx.channel.id}') | ||||
|             self._clients.append_sent_message_count(self._bot.user.id, ctx.guild.id, 1) | ||||
|             self._db.save_changes() | ||||
|             if wait_before_delete is not None: | ||||
|                 await asyncio.sleep(wait_before_delete) | ||||
|  | ||||
|             if is_persistent: | ||||
|                 await self.delete_message(ctx.message) | ||||
|                 return | ||||
|  | ||||
|             await self.delete_messages(List(discord.Message, [msg, ctx.message]), ctx.guild.id) | ||||
| @@ -1 +1,26 @@ | ||||
| # imports:  | ||||
| # -*- coding: utf-8 -*- | ||||
|  | ||||
| """ | ||||
| bot-data Keksdose bot - data | ||||
| ~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| Discord bot  for the Keksdose discord Server - database package | ||||
|  | ||||
| :copyright: (c) 2022 sh-edraft.de | ||||
| :license: MIT, see LICENSE for more details. | ||||
|  | ||||
| """ | ||||
|  | ||||
| __title__ = 'bot_data' | ||||
| __author__ = 'Sven Heidemann' | ||||
| __license__ = 'MIT' | ||||
| __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||
| __version__ = '1.0.0.dev1' | ||||
|  | ||||
| from collections import namedtuple | ||||
|  | ||||
|  | ||||
| # imports | ||||
|  | ||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||
| version_info = VersionInfo(major='1', minor='0', micro='0.dev1') | ||||
|   | ||||
							
								
								
									
										26
									
								
								src/bot_data/abc/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/bot_data/abc/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
|  | ||||
| """ | ||||
| bot-data Keksdose bot - data | ||||
| ~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| Discord bot  for the Keksdose discord Server - database package | ||||
|  | ||||
| :copyright: (c) 2022 sh-edraft.de | ||||
| :license: MIT, see LICENSE for more details. | ||||
|  | ||||
| """ | ||||
|  | ||||
| __title__ = 'bot_data.abc' | ||||
| __author__ = 'Sven Heidemann' | ||||
| __license__ = 'MIT' | ||||
| __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||
| __version__ = '1.0.0.dev1' | ||||
|  | ||||
| from collections import namedtuple | ||||
|  | ||||
|  | ||||
| # imports | ||||
|  | ||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||
| version_info = VersionInfo(major='1', minor='0', micro='0.dev1') | ||||
							
								
								
									
										53
									
								
								src/bot_data/abc/client_repository_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/bot_data/abc/client_repository_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| from abc import ABC, abstractmethod | ||||
| from typing import Optional | ||||
|  | ||||
| from cpl_query.extension import List | ||||
| from bot_data.model.client import Client | ||||
|  | ||||
|  | ||||
| class ClientRepositoryABC(ABC): | ||||
|  | ||||
|     @abstractmethod | ||||
|     def __init__(self): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_clients(self) -> List[Client]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_client_by_id(self, client_id: int) -> Client: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_client_by_discord_id(self, discord_id: int) -> Client: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def find_client_by_discord_id(self, discord_id: int) -> Optional[Client]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def find_client_by_server_id(self, server_id: int) -> Optional[Client]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def find_client_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> Optional[Client]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def add_client(self, client: Client): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def update_client(self, client: Client): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def delete_client(self, client: Client): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def append_sent_message_count(self, client_id: int, server_id: int, value: int): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def append_received_message_count(self, client_id: int, server_id: int, value: int): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def append_deleted_message_count(self, client_id: int, server_id: int, value: int): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def append_received_command_count(self, client_id: int, server_id: int, value: int): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def append_moved_users_count(self, client_id: int, server_id: int, value: int): pass | ||||
							
								
								
									
										30
									
								
								src/bot_data/abc/known_user_repository_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/bot_data/abc/known_user_repository_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| from abc import ABC, abstractmethod | ||||
| from typing import Optional | ||||
|  | ||||
| from cpl_query.extension import List | ||||
|  | ||||
| from bot_data.model.known_user import KnownUser | ||||
|  | ||||
|  | ||||
| class KnownUserRepositoryABC(ABC): | ||||
|  | ||||
|     @abstractmethod | ||||
|     def __init__(self): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_users(self) -> List[KnownUser]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_user_by_id(self, id: int) -> KnownUser: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_user_by_discord_id(self, discord_id: int) -> KnownUser: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def find_user_by_discord_id(self, discord_id: int) -> Optional[KnownUser]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def add_user(self, known_user: KnownUser): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def delete_user(self, known_user: KnownUser): pass | ||||
							
								
								
									
										13
									
								
								src/bot_data/abc/migration_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/bot_data/abc/migration_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| from abc import ABC, abstractmethod | ||||
|  | ||||
|  | ||||
| class MigrationABC(ABC): | ||||
|  | ||||
|     @abstractmethod | ||||
|     def __init__(self): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def upgrade(self): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def downgrade(self): pass | ||||
							
								
								
									
										33
									
								
								src/bot_data/abc/server_repository_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/bot_data/abc/server_repository_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| from abc import ABC, abstractmethod | ||||
| from typing import Optional | ||||
|  | ||||
| from cpl_query.extension import List | ||||
|  | ||||
| from bot_data.model.server import Server | ||||
|  | ||||
|  | ||||
| class ServerRepositoryABC(ABC): | ||||
|  | ||||
|     @abstractmethod | ||||
|     def __init__(self): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_servers(self) -> List[Server]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_server_by_id(self, id: int) -> Server: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_server_by_discord_id(self, discord_id: int) -> Server: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def find_server_by_discord_id(self, discord_id: int) -> Optional[Server]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def add_server(self, server: Server): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def update_server(self, server: Server): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def delete_server(self, server: Server): pass | ||||
							
								
								
									
										35
									
								
								src/bot_data/abc/user_joined_server_repository_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/bot_data/abc/user_joined_server_repository_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| from abc import ABC, abstractmethod | ||||
| from typing import Optional | ||||
|  | ||||
| from cpl_query.extension import List | ||||
| from bot_data.model.user_joined_server import UserJoinedServer | ||||
|  | ||||
|  | ||||
| class UserJoinedServerRepositoryABC(ABC): | ||||
|  | ||||
|     @abstractmethod | ||||
|     def __init__(self): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_user_joined_servers(self) -> List[UserJoinedServer]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_user_joined_server_by_id(self, id: int) -> UserJoinedServer: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_user_joined_servers_by_user_id(self, user_id: int) -> list[UserJoinedServer]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_active_user_joined_server_by_user_id(self, user_id: int) -> UserJoinedServer: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def find_active_user_joined_server_by_user_id(self, user_id: int) -> Optional[UserJoinedServer]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def add_user_joined_server(self, user_joined_server: UserJoinedServer): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def update_user_joined_server(self, user_joined_server: UserJoinedServer): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def delete_user_joined_server(self, user_joined_server: UserJoinedServer): pass | ||||
							
								
								
									
										37
									
								
								src/bot_data/abc/user_joined_voice_channel_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/bot_data/abc/user_joined_voice_channel_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| from abc import ABC, abstractmethod | ||||
| from typing import Optional | ||||
|  | ||||
| from cpl_query.extension import List | ||||
| from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel | ||||
|  | ||||
| class UserJoinedVoiceChannelRepositoryABC(ABC): | ||||
|  | ||||
|     @abstractmethod | ||||
|     def __init__(self): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_user_joined_voice_channels(self) -> List[UserJoinedVoiceChannel]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_user_joined_voice_channel_by_id(self, id: int) -> UserJoinedVoiceChannel: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_user_joined_voice_channels_by_user_id(self, user_id: int) -> list[UserJoinedVoiceChannel]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_active_user_joined_voice_channel_by_user_id(self, user_id: int) -> UserJoinedVoiceChannel: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def find_active_user_joined_voice_channel_by_user_id(self, user_id: int) -> Optional[UserJoinedVoiceChannel]: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def find_active_user_joined_voice_channels_by_user_id(self, user_id: int) -> List[Optional[UserJoinedVoiceChannel]]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def add_user_joined_voice_channel(self, user_joined_voice_channel: UserJoinedVoiceChannel): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def update_user_joined_voice_channel(self, user_joined_voice_channel: UserJoinedVoiceChannel): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def delete_user_joined_voice_channel(self, user_joined_voice_channel: UserJoinedVoiceChannel): pass | ||||
							
								
								
									
										36
									
								
								src/bot_data/abc/user_repository_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/bot_data/abc/user_repository_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| from abc import ABC, abstractmethod | ||||
| from typing import Optional | ||||
|  | ||||
| from cpl_query.extension import List | ||||
|  | ||||
| from bot_data.model.user import User | ||||
|  | ||||
|  | ||||
| class UserRepositoryABC(ABC): | ||||
|  | ||||
|     @abstractmethod | ||||
|     def __init__(self): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_users(self) -> List[User]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_user_by_id(self, id: int) -> User: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_users_by_discord_id(self, discord_id: int) -> List[User]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def get_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> User: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def find_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> Optional[User]: pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def add_user(self, user: User): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def update_user(self, user: User): pass | ||||
|      | ||||
|     @abstractmethod | ||||
|     def delete_user(self, user: User): pass | ||||
							
								
								
									
										33
									
								
								src/bot_data/db_context.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/bot_data/db_context.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| from cpl_core.database import DatabaseSettings | ||||
| from cpl_core.database.context import DatabaseContext | ||||
| from cpl_core.logging import LoggerABC | ||||
|  | ||||
|  | ||||
| class DBContext(DatabaseContext): | ||||
|  | ||||
|     def __init__(self, logger: LoggerABC): | ||||
|          | ||||
|         self._logger = logger | ||||
|          | ||||
|         DatabaseContext.__init__(self) | ||||
|  | ||||
|     def connect(self, database_settings: DatabaseSettings): | ||||
|         try: | ||||
|             self._logger.debug(__name__, "Connecting to database") | ||||
|             self._db.connect(database_settings) | ||||
|  | ||||
|             self.save_changes() | ||||
|             self._logger.info(__name__, "Connected to database") | ||||
|         except Exception as e: | ||||
|             self._logger.fatal(__name__, "Connecting to database failed", e) | ||||
|          | ||||
|     def save_changes(self): | ||||
|         try: | ||||
|             self._logger.trace(__name__, "Save changes") | ||||
|             super(DBContext, self).save_changes() | ||||
|             self._logger.debug(__name__, "Saved changes") | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, "Saving changes failed", e) | ||||
|      | ||||
|     def select(self, statement: str) -> list[tuple]: | ||||
|         return super(DBContext, self).select(statement) | ||||
							
								
								
									
										26
									
								
								src/bot_data/migration/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/bot_data/migration/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
|  | ||||
| """ | ||||
| bot-data Keksdose bot - data | ||||
| ~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| Discord bot  for the Keksdose discord Server - database package | ||||
|  | ||||
| :copyright: (c) 2022 sh-edraft.de | ||||
| :license: MIT, see LICENSE for more details. | ||||
|  | ||||
| """ | ||||
|  | ||||
| __title__ = 'bot_data.migration' | ||||
| __author__ = 'Sven Heidemann' | ||||
| __license__ = 'MIT' | ||||
| __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||
| __version__ = '1.0.0.dev1' | ||||
|  | ||||
| from collections import namedtuple | ||||
|  | ||||
|  | ||||
| # imports | ||||
|  | ||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||
| version_info = VersionInfo(major='1', minor='0', micro='0.dev1') | ||||
							
								
								
									
										123
									
								
								src/bot_data/migration/initial_migration.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								src/bot_data/migration/initial_migration.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | ||||
| from cpl_core.logging import LoggerABC | ||||
|  | ||||
| from bot_data.abc.migration_abc import MigrationABC | ||||
| from bot_data.db_context import DBContext | ||||
|  | ||||
|  | ||||
| class InitialMigration(MigrationABC): | ||||
|  | ||||
|     def __init__(self, logger: LoggerABC, db: DBContext): | ||||
|         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 `MigrationHistory` ( | ||||
|                 `MigrationId` VARCHAR(255), | ||||
|                 `CreatedAt` DATETIME(6), | ||||
|                 `LastModifiedAt` DATETIME(6), | ||||
|                 PRIMARY KEY(`MigrationId`) | ||||
|             ); | ||||
|             """) | ||||
|         ) | ||||
|  | ||||
|         self._cursor.execute( | ||||
|             str(f""" | ||||
|             CREATE TABLE IF NOT EXISTS `Servers` ( | ||||
|                 `ServerId` BIGINT NOT NULL AUTO_INCREMENT, | ||||
|                 `DiscordServerId` BIGINT NOT NULL, | ||||
|                 `CreatedAt` DATETIME(6), | ||||
|                 `LastModifiedAt` DATETIME(6), | ||||
|                 PRIMARY KEY(`ServerId`) | ||||
|             ); | ||||
|             """) | ||||
|         ) | ||||
|  | ||||
|         self._cursor.execute( | ||||
|             str(f""" | ||||
|             CREATE TABLE IF NOT EXISTS `Users` ( | ||||
|                 `UserId` BIGINT NOT NULL AUTO_INCREMENT, | ||||
|                 `DiscordId` BIGINT NOT NULL, | ||||
|                 `XP` BIGINT NOT NULL DEFAULT 0, | ||||
|                 `ServerId` BIGINT, | ||||
|                 `CreatedAt` DATETIME(6), | ||||
|                 `LastModifiedAt` DATETIME(6), | ||||
|                 FOREIGN KEY (`ServerId`) REFERENCES Servers(`ServerId`), | ||||
|                 PRIMARY KEY(`UserId`) | ||||
|             ); | ||||
|             """) | ||||
|         ) | ||||
|  | ||||
|         self._cursor.execute( | ||||
|             str(f""" | ||||
|             CREATE TABLE IF NOT EXISTS `Clients` ( | ||||
|                 `ClientId` BIGINT NOT NULL AUTO_INCREMENT, | ||||
|                 `DiscordClientId` BIGINT NOT NULL, | ||||
|                 `SentMessageCount` BIGINT NOT NULL DEFAULT 0, | ||||
|                 `ReceivedMessageCount` BIGINT NOT NULL DEFAULT 0, | ||||
|                 `DeletedMessageCount` BIGINT NOT NULL DEFAULT 0, | ||||
|                 `ReceivedCommandsCount` BIGINT NOT NULL DEFAULT 0, | ||||
|                 `MovedUsersCount` BIGINT NOT NULL DEFAULT 0, | ||||
|                 `ServerId` BIGINT, | ||||
|                 `CreatedAt` DATETIME(6), | ||||
|                 `LastModifiedAt` DATETIME(6), | ||||
|                 FOREIGN KEY (`ServerId`) REFERENCES Servers(`ServerId`), | ||||
|                 PRIMARY KEY(`ClientId`) | ||||
|             ); | ||||
|             """) | ||||
|         ) | ||||
|  | ||||
|         self._cursor.execute( | ||||
|             str(f""" | ||||
|             CREATE TABLE IF NOT EXISTS `KnownUsers` ( | ||||
|                 `KnownUserId` BIGINT NOT NULL AUTO_INCREMENT, | ||||
|                 `DiscordId` BIGINT NOT NULL, | ||||
|                 `CreatedAt` DATETIME(6), | ||||
|                 `LastModifiedAt` DATETIME(6), | ||||
|                 PRIMARY KEY(`KnownUserId`) | ||||
|             ); | ||||
|             """) | ||||
|         ) | ||||
|  | ||||
|         self._cursor.execute( | ||||
|             str(f""" | ||||
|             CREATE TABLE IF NOT EXISTS `UserJoinedServers` ( | ||||
|                 `JoinId` BIGINT NOT NULL AUTO_INCREMENT, | ||||
|                 `UserId` BIGINT NOT NULL, | ||||
|                 `JoinedOn` DATETIME(6) NOT NULL, | ||||
|                 `LeavedOn` DATETIME(6), | ||||
|                 `CreatedAt` DATETIME(6), | ||||
|                 `LastModifiedAt` DATETIME(6), | ||||
|                 FOREIGN KEY (`UserId`) REFERENCES Users(`UserId`), | ||||
|                 PRIMARY KEY(`JoinId`) | ||||
|             ); | ||||
|             """) | ||||
|         ) | ||||
|  | ||||
|         self._cursor.execute( | ||||
|             str(f""" | ||||
|             CREATE TABLE IF NOT EXISTS `UserJoinedVoiceChannel` ( | ||||
|                 `JoinId` BIGINT NOT NULL AUTO_INCREMENT, | ||||
|                 `UserId` BIGINT NOT NULL, | ||||
|                 `DiscordChannelId` BIGINT NOT NULL, | ||||
|                 `JoinedOn` DATETIME(6) NOT NULL, | ||||
|                 `LeavedOn` DATETIME(6), | ||||
|                 `CreatedAt` DATETIME(6), | ||||
|                 `LastModifiedAt` DATETIME(6), | ||||
|                 FOREIGN KEY (`UserId`) REFERENCES Users(`UserId`), | ||||
|                 PRIMARY KEY(`JoinId`) | ||||
|             ); | ||||
|             """) | ||||
|         ) | ||||
|  | ||||
|     def downgrade(self): | ||||
|         self._cursor.execute('DROP TABLE `Servers`;') | ||||
|         self._cursor.execute('DROP TABLE `Users`;') | ||||
|         self._cursor.execute('DROP TABLE `Clients`;') | ||||
|         self._cursor.execute('DROP TABLE `KnownUsers`;') | ||||
|         self._cursor.execute('DROP TABLE `UserJoinedServers`;') | ||||
|         self._cursor.execute('DROP TABLE `UserJoinedVoiceChannel`;') | ||||
							
								
								
									
										26
									
								
								src/bot_data/model/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/bot_data/model/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
|  | ||||
| """ | ||||
| bot-data Keksdose bot - data | ||||
| ~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| Discord bot  for the Keksdose discord Server - database package | ||||
|  | ||||
| :copyright: (c) 2022 sh-edraft.de | ||||
| :license: MIT, see LICENSE for more details. | ||||
|  | ||||
| """ | ||||
|  | ||||
| __title__ = 'bot_data.model' | ||||
| __author__ = 'Sven Heidemann' | ||||
| __license__ = 'MIT' | ||||
| __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||
| __version__ = '1.0.0.dev1' | ||||
|  | ||||
| from collections import namedtuple | ||||
|  | ||||
|  | ||||
| # imports | ||||
|  | ||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||
| version_info = VersionInfo(major='1', minor='0', micro='0.dev1') | ||||
							
								
								
									
										170
									
								
								src/bot_data/model/client.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								src/bot_data/model/client.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | ||||
| from datetime import datetime | ||||
| from cpl_core.database import TableABC | ||||
|  | ||||
| from bot_data.model.server import Server | ||||
|  | ||||
|  | ||||
| class Client(TableABC): | ||||
|  | ||||
|     def __init__(self, | ||||
|                 dc_id: int, | ||||
|                 smc: int, | ||||
|                 rmc: int, | ||||
|                 dmc: int, | ||||
|                 rcc: int, | ||||
|                 muc: int, | ||||
|                 server: Server, | ||||
|                 created_at: datetime = None, | ||||
|                 modified_at: datetime = None, | ||||
|                 id=0 | ||||
|     ): | ||||
|         self._client_id = id | ||||
|         self._discord_client_id = dc_id | ||||
|         self._sent_message_count = smc | ||||
|         self._received_message_count = rmc | ||||
|         self._deleted_message_count = dmc | ||||
|         self._received_command_count = rcc | ||||
|         self._moved_users_count = muc | ||||
|         self._server: 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 client_id(self) -> int: | ||||
|         return self._client_id | ||||
|  | ||||
|     @property | ||||
|     def discord_id(self) -> int: | ||||
|         return self._discord_client_id | ||||
|  | ||||
|     @property | ||||
|     def sent_message_count(self) -> int: | ||||
|         return self._sent_message_count | ||||
|  | ||||
|     @sent_message_count.setter | ||||
|     def sent_message_count(self, value: int): | ||||
|         self._modified_at = datetime.now().isoformat() | ||||
|         self._sent_message_count = value | ||||
|  | ||||
|     @property | ||||
|     def received_message_count(self) -> int: | ||||
|         return self._received_message_count | ||||
|  | ||||
|     @received_message_count.setter | ||||
|     def received_message_count(self, value: int): | ||||
|         self._modified_at = datetime.now().isoformat() | ||||
|         self._received_message_count = value | ||||
|  | ||||
|     @property | ||||
|     def deleted_message_count(self) -> int: | ||||
|         return self._deleted_message_count | ||||
|  | ||||
|     @deleted_message_count.setter | ||||
|     def deleted_message_count(self, value: int): | ||||
|         self._modified_at = datetime.now().isoformat() | ||||
|         self._deleted_message_count = value | ||||
|  | ||||
|     @property | ||||
|     def received_command_count(self) -> int: | ||||
|         return self._received_command_count | ||||
|  | ||||
|     @received_command_count.setter | ||||
|     def received_command_count(self, value: int): | ||||
|         self._modified_at = datetime.now().isoformat() | ||||
|         self._received_command_count = value | ||||
|  | ||||
|     @property | ||||
|     def moved_users_count(self) -> int: | ||||
|         return self._moved_users_count | ||||
|  | ||||
|     @moved_users_count.setter | ||||
|     def moved_users_count(self, value: int): | ||||
|         self._modified_at = datetime.now().isoformat() | ||||
|         self._moved_users_count = value | ||||
|  | ||||
|     @property | ||||
|     def server(self) -> Server: | ||||
|         return self._server | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_all_string() -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `Clients`; | ||||
|         """) | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_by_id_string(id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `Clients` | ||||
|             WHERE `ClientId` = {id}; | ||||
|         """) | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_by_discord_id_string(id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `Clients` | ||||
|             WHERE `DiscordClientId` = {id}; | ||||
|         """) | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_by_server_id_string(id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `Clients` | ||||
|             WHERE `ServerId` = {id}; | ||||
|         """) | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_by_discord_id_and_server_id_string(id: int, server_id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `Clients` | ||||
|             WHERE `DiscordClientId` = {id} | ||||
|             AND `ServerId` = {server_id}; | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def insert_string(self) -> str: | ||||
|         return str(f""" | ||||
|             INSERT INTO `Clients` ( | ||||
|                 `DiscordClientId`, | ||||
|                 `SentMessageCount`, | ||||
|                 `ReceivedMessageCount`, | ||||
|                 `DeletedMessageCount`, | ||||
|                 `ReceivedCommandsCount`, | ||||
|                 `MovedUsersCount`, | ||||
|                 `ServerId`, | ||||
|                 `CreatedAt`, | ||||
|                 `LastModifiedAt` | ||||
|             ) VALUES ( | ||||
|                 {self._discord_client_id}, | ||||
|                 {self._sent_message_count}, | ||||
|                 {self._received_message_count}, | ||||
|                 {self._deleted_message_count}, | ||||
|                 {self._received_message_count}, | ||||
|                 {self._moved_users_count}, | ||||
|                 {self._server.server_id}, | ||||
|                 '{self._created_at}', | ||||
|                 '{self._modified_at}' | ||||
|             ); | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def udpate_string(self) -> str: | ||||
|         return str(f""" | ||||
|             UPDATE `Clients` | ||||
|             SET `SentMessageCount` = {self._sent_message_count}, | ||||
|             `ReceivedMessageCount` = {self._received_message_count}, | ||||
|             `DeletedMessageCount` = {self._deleted_message_count}, | ||||
|             `ReceivedCommandsCount` = {self._received_command_count}, | ||||
|             `MovedUsersCount` = {self._moved_users_count}, | ||||
|             `LastModifiedAt` = '{self._modified_at}' | ||||
|             WHERE `ClientId` = {self._client_id}; | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def delete_string(self) -> str: | ||||
|         return str(f""" | ||||
|             DELETE FROM `Clients` | ||||
|             WHERE `ClientId` = {self._client_id}; | ||||
|         """) | ||||
							
								
								
									
										67
									
								
								src/bot_data/model/known_user.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/bot_data/model/known_user.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| from datetime import datetime | ||||
| from typing import Optional | ||||
| from cpl_core.database import TableABC | ||||
|  | ||||
| from bot_data.model.server import Server | ||||
|  | ||||
|  | ||||
| class KnownUser(TableABC): | ||||
|  | ||||
|     def __init__(self, dc_id: int, created_at: datetime = None, modified_at: datetime = None, id=0): | ||||
|         self._known_user_id = id | ||||
|         self._discord_id = dc_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 known_user_id(self) -> int: | ||||
|         return self._known_user_id | ||||
|  | ||||
|     @property | ||||
|     def discord_id(self) -> int: | ||||
|         return self._discord_id | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_all_string() -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `KnownUsers`; | ||||
|         """) | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_by_id_string(id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `KnownUsers` | ||||
|             WHERE `KnownUserId` = {id}; | ||||
|         """) | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_by_discord_id_string(id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `KnownUsers` | ||||
|             WHERE `DiscordId` = {id}; | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def insert_string(self) -> str: | ||||
|         return str(f""" | ||||
|             INSERT INTO `KnownUsers` ( | ||||
|                 `DiscordId`, `CreatedAt`, `LastModifiedAt` | ||||
|             ) VALUES ( | ||||
|                 {self._discord_id}, | ||||
|                 '{self._created_at}', | ||||
|                 '{self._modified_at}' | ||||
|             ); | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def udpate_string(self) -> str: | ||||
|         return '' | ||||
|  | ||||
|     @property | ||||
|     def delete_string(self) -> str: | ||||
|         return str(f""" | ||||
|             DELETE FROM `KnownUsers` | ||||
|             WHERE `Id` = {self._known_user_id}; | ||||
|         """) | ||||
							
								
								
									
										47
									
								
								src/bot_data/model/migration_history.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/bot_data/model/migration_history.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| from cpl_core.database import TableABC | ||||
|  | ||||
|  | ||||
| class MigrationHistory(TableABC): | ||||
|  | ||||
|     def __init__(self, id: str): | ||||
|         self._id = id | ||||
|  | ||||
|         TableABC.__init__(self) | ||||
|      | ||||
|     @property | ||||
|     def migration_id(self) -> str: | ||||
|         return self._id | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_by_id_string(id: str) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `MigrationHistory` | ||||
|             WHERE `MigrationId` = '{id}'; | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def insert_string(self) -> str: | ||||
|         return str(f""" | ||||
|             INSERT INTO `MigrationHistory` ( | ||||
|                 `MigrationId`, `CreatedAt`, `LastModifiedAt` | ||||
|             ) VALUES ( | ||||
|                 '{self._id}', | ||||
|                 '{self._created_at}', | ||||
|                 '{self._modified_at}' | ||||
|             ); | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def udpate_string(self) -> str: | ||||
|         return str(f""" | ||||
|             UPDATE `MigrationHistory` | ||||
|             SET LastModifiedAt` = '{self._modified_at}' | ||||
|             WHERE `MigrationId` = '{self._id}'; | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def delete_string(self) -> str: | ||||
|         return str(f""" | ||||
|             DELETE FROM `MigrationHistory` | ||||
|             WHERE `MigrationId` = '{self._id}'; | ||||
|         """) | ||||
							
								
								
									
										71
									
								
								src/bot_data/model/server.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/bot_data/model/server.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| from datetime import datetime | ||||
| from typing import Optional | ||||
|  | ||||
| from cpl_core.database import TableABC | ||||
|  | ||||
|  | ||||
| class Server(TableABC): | ||||
|  | ||||
|     def __init__(self, dc_id: int, created_at: datetime=None, modified_at: datetime=None, id=0): | ||||
|         self._server_id = id | ||||
|         self._discord_server_id = dc_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 server_id(self) -> int: | ||||
|         return self._server_id | ||||
|  | ||||
|     @property | ||||
|     def discord_server_id(self) -> int: | ||||
|         return self._discord_server_id | ||||
|          | ||||
|     @staticmethod | ||||
|     def get_select_all_string() -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `Servers`; | ||||
|         """) | ||||
|          | ||||
|     @staticmethod | ||||
|     def get_select_by_id_string(id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `Servers` | ||||
|             WHERE `ServerId` = {id}; | ||||
|         """) | ||||
|          | ||||
|     @staticmethod | ||||
|     def get_select_by_discord_id_string(id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `Servers` | ||||
|             WHERE `DiscordServerId` = {id}; | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def insert_string(self) -> str: | ||||
|         return str(f""" | ||||
|             INSERT INTO `Servers` ( | ||||
|                 `DiscordServerId`, `CreatedAt`, `LastModifiedAt` | ||||
|             ) VALUES ( | ||||
|                 {self._discord_server_id}, | ||||
|                 '{self._created_at}', | ||||
|                 '{self._modified_at}' | ||||
|             ); | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def udpate_string(self) -> str: | ||||
|         return str(f""" | ||||
|             UPDATE `Servers` | ||||
|             SET `DiscordServerId` = {self._discord_server_id}, | ||||
|             `LastModifiedAt` = '{self._modified_at}' | ||||
|             WHERE `Id` = {self._server_id}; | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def delete_string(self) -> str: | ||||
|         return str(f""" | ||||
|             DELETE FROM `Servers` | ||||
|             WHERE `Id` = {self._server_id}; | ||||
|         """) | ||||
							
								
								
									
										97
									
								
								src/bot_data/model/user.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/bot_data/model/user.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| from datetime import datetime | ||||
| from typing import Optional | ||||
| from cpl_core.database import TableABC | ||||
|  | ||||
| from bot_data.model.server import Server | ||||
|  | ||||
|  | ||||
| class User(TableABC): | ||||
|  | ||||
|     def __init__(self, dc_id: int, xp: int, server: Optional[Server], created_at: datetime = None, modified_at: datetime = None, id=0): | ||||
|         self._user_id = id | ||||
|         self._discord_id = dc_id | ||||
|         self._xp = xp | ||||
|         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 user_id(self) -> int: | ||||
|         return self._user_id | ||||
|  | ||||
|     @property | ||||
|     def discord_id(self) -> int: | ||||
|         return self._discord_id | ||||
|  | ||||
|     @property | ||||
|     def xp(self) -> int: | ||||
|         return self._xp | ||||
|  | ||||
|     @xp.setter | ||||
|     def xp(self, value: int): | ||||
|         self._modified_at = datetime.now().isoformat() | ||||
|         self._xp = value | ||||
|  | ||||
|     @property | ||||
|     def server(self) -> Optional[Server]: | ||||
|         return self._server | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_all_string() -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `Users`; | ||||
|         """) | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_by_id_string(id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `Users` | ||||
|             WHERE `UserId` = {id}; | ||||
|         """) | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_by_discord_id_string(id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `Users` | ||||
|             WHERE `DiscordId` = {id}; | ||||
|         """) | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_by_discord_id_and_server_id_string(dc_id: int, s_id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `Users` | ||||
|             WHERE `DiscordId` = {dc_id} | ||||
|             AND `ServerId` = {s_id}; | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def insert_string(self) -> str: | ||||
|         return str(f""" | ||||
|             INSERT INTO `Users` ( | ||||
|                 `DiscordId`, `XP`, `ServerId`, `CreatedAt`, `LastModifiedAt` | ||||
|             ) VALUES ( | ||||
|                 {self._discord_id}, | ||||
|                 {self._xp}, | ||||
|                 {self._server.server_id}, | ||||
|                 '{self._created_at}', | ||||
|                 '{self._modified_at}' | ||||
|             ); | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def udpate_string(self) -> str: | ||||
|         return str(f""" | ||||
|             UPDATE `Users` | ||||
|             SET `XP` = {self._xp}, | ||||
|             `LastModifiedAt` = '{self._modified_at}' | ||||
|             WHERE `UserId` = {self._user_id}; | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def delete_string(self) -> str: | ||||
|         return str(f""" | ||||
|             DELETE FROM `Users` | ||||
|             WHERE `UserId` = {self._user_id}; | ||||
|         """) | ||||
							
								
								
									
										116
									
								
								src/bot_data/model/user_joined_server.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/bot_data/model/user_joined_server.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | ||||
| from datetime import datetime | ||||
| from typing import Optional | ||||
|  | ||||
| from cpl_core.database import TableABC | ||||
|  | ||||
| from bot_data.model.user import User | ||||
| from bot_data.model.server import Server | ||||
|  | ||||
|  | ||||
| class UserJoinedServer(TableABC): | ||||
|  | ||||
|     def __init__(self, user: User, joined_on: datetime, leaved_on: datetime=None, created_at: datetime=None, modified_at: datetime=None, id=0): | ||||
|         self._join_id = id | ||||
|         self._user = user | ||||
|         self._joined_on = joined_on | ||||
|         self._leaved_on = leaved_on | ||||
|          | ||||
|         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 join_id(self) -> int: | ||||
|         return self._join_id | ||||
|  | ||||
|     @property | ||||
|     def user(self) -> User: | ||||
|         return self._user | ||||
|  | ||||
|     @property | ||||
|     def joined_on(self) -> datetime: | ||||
|         return self._joined_on | ||||
|  | ||||
|     @joined_on.setter | ||||
|     def joined_on(self, value: datetime): | ||||
|         self._modified_at = datetime.now() | ||||
|         self.joined_on = value | ||||
|  | ||||
|     @property | ||||
|     def leaved_on(self) -> datetime: | ||||
|         return self._leaved_on | ||||
|  | ||||
|     @leaved_on.setter | ||||
|     def leaved_on(self, value: datetime): | ||||
|         self._modified_at = datetime.now() | ||||
|         self._leaved_on = value | ||||
|          | ||||
|     @staticmethod | ||||
|     def get_select_all_string() -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `UserJoinedServers`; | ||||
|         """) | ||||
|          | ||||
|     @staticmethod | ||||
|     def get_select_by_id_string(id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `UserJoinedServers` | ||||
|             WHERE `JoinId` = {id}; | ||||
|         """) | ||||
|          | ||||
|     @staticmethod | ||||
|     def get_select_by_user_id_string(id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `UserJoinedServers` | ||||
|             WHERE `UserId` = {id}; | ||||
|         """) | ||||
|          | ||||
|     @staticmethod | ||||
|     def get_select_active_by_user_id_string(id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `UserJoinedServers` | ||||
|             WHERE `UserId` = {id} | ||||
|             AND `LeavedOn` IS NULL; | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def insert_string(self) -> str: | ||||
|         if self._leaved_on is not None: | ||||
|             return str(f""" | ||||
|                 INSERT INTO `UserJoinedServers` ( | ||||
|                     `UserId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt` | ||||
|                 ) VALUES ( | ||||
|                     {self._user.user_id}, | ||||
|                     '{self._joined_on}', | ||||
|                     '{self._leaved_on}', | ||||
|                     '{self._created_at}', | ||||
|                     '{self._modified_at}' | ||||
|                 ); | ||||
|             """) | ||||
|         else: | ||||
|             return str(f""" | ||||
|                 INSERT INTO `UserJoinedServers` ( | ||||
|                     `UserId`, `JoinedOn`, `CreatedAt`, `LastModifiedAt` | ||||
|                 ) VALUES ( | ||||
|                     {self._user.user_id}, | ||||
|                     '{self._joined_on}', | ||||
|                     '{self._created_at}', | ||||
|                     '{self._modified_at}' | ||||
|                 ); | ||||
|             """) | ||||
|  | ||||
|     @property | ||||
|     def udpate_string(self) -> str: | ||||
|         return str(f""" | ||||
|             UPDATE `UserJoinedServers` | ||||
|             SET `LeavedOn` = '{self._leaved_on}', | ||||
|             `LastModifiedAt` = '{self._modified_at}' | ||||
|             WHERE `UserId` = {self._user.user_id}; | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def delete_string(self) -> str: | ||||
|         return str(f""" | ||||
|             DELETE FROM `UserJoinedServers` | ||||
|             WHERE `Id` = {self._join_id}; | ||||
|         """) | ||||
							
								
								
									
										121
									
								
								src/bot_data/model/user_joined_voice_channel.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								src/bot_data/model/user_joined_voice_channel.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,121 @@ | ||||
| from datetime import datetime | ||||
|  | ||||
| from cpl_core.database import TableABC | ||||
|  | ||||
| from bot_data.model.user import User | ||||
|  | ||||
|  | ||||
| class UserJoinedVoiceChannel(TableABC): | ||||
|  | ||||
|     def __init__(self, user: User, dc_channel_id: int, joined_on: datetime, leaved_on: datetime = None, created_at: datetime = None, modified_at: datetime = None, id=0): | ||||
|         self._join_id = id | ||||
|         self._dc_channel_id = dc_channel_id | ||||
|         self._user = user | ||||
|         self._joined_on = joined_on | ||||
|         self._leaved_on = leaved_on | ||||
|  | ||||
|         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 join_id(self) -> int: | ||||
|         return self._join_id | ||||
|      | ||||
|     @property | ||||
|     def dc_channel_id(self) -> int: | ||||
|         return self._dc_channel_id | ||||
|  | ||||
|     @property | ||||
|     def user(self) -> User: | ||||
|         return self._user | ||||
|  | ||||
|     @property | ||||
|     def joined_on(self) -> datetime: | ||||
|         return self._joined_on | ||||
|  | ||||
|     @joined_on.setter | ||||
|     def joined_on(self, value: datetime): | ||||
|         self._modified_at = datetime.now() | ||||
|         self.joined_on = value | ||||
|  | ||||
|     @property | ||||
|     def leaved_on(self) -> datetime: | ||||
|         return self._leaved_on | ||||
|  | ||||
|     @leaved_on.setter | ||||
|     def leaved_on(self, value: datetime): | ||||
|         self._modified_at = datetime.now() | ||||
|         self._leaved_on = value | ||||
|          | ||||
|     @staticmethod | ||||
|     def get_select_all_string() -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `UserJoinedVoiceChannel`; | ||||
|         """) | ||||
|          | ||||
|     @staticmethod | ||||
|     def get_select_by_id_string(id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `UserJoinedVoiceChannel` | ||||
|             WHERE `JoinId` = {id}; | ||||
|         """) | ||||
|          | ||||
|     @staticmethod | ||||
|     def get_select_by_user_id_string(id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `UserJoinedVoiceChannel` | ||||
|             WHERE `UserId` = {id}; | ||||
|         """) | ||||
|          | ||||
|     @staticmethod | ||||
|     def get_select_active_by_user_id_string(id: int) -> str: | ||||
|         return str(f""" | ||||
|             SELECT * FROM `UserJoinedVoiceChannel` | ||||
|             WHERE `UserId` = {id} | ||||
|             AND `LeavedOn` IS NULL; | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def insert_string(self) -> str: | ||||
|         if self._leaved_on is not None: | ||||
|             return str(f""" | ||||
|                 INSERT INTO `UserJoinedVoiceChannel` ( | ||||
|                     `UserId`, `DiscordChannelId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt` | ||||
|                 ) VALUES ( | ||||
|                     {self._user.user_id}, | ||||
|                     {self._dc_channel_id}, | ||||
|                     '{self._joined_on}', | ||||
|                     '{self._leaved_on}', | ||||
|                     '{self._created_at}', | ||||
|                     '{self._modified_at}' | ||||
|                 ); | ||||
|             """) | ||||
|         else: | ||||
|             return str(f""" | ||||
|                 INSERT INTO `UserJoinedVoiceChannel` ( | ||||
|                     `UserId`, `DiscordChannelId`, `JoinedOn`, `CreatedAt`, `LastModifiedAt` | ||||
|                 ) VALUES ( | ||||
|                     {self._user.user_id}, | ||||
|                     {self._dc_channel_id}, | ||||
|                     '{self._joined_on}', | ||||
|                     '{self._created_at}', | ||||
|                     '{self._modified_at}' | ||||
|                 ); | ||||
|             """) | ||||
|  | ||||
|     @property | ||||
|     def udpate_string(self) -> str: | ||||
|         return str(f""" | ||||
|             UPDATE `UserJoinedVoiceChannel` | ||||
|             SET `LeavedOn` = '{self._leaved_on}', | ||||
|             `LastModifiedAt` = '{self._modified_at}' | ||||
|             WHERE `JoinId` = {self._join_id}; | ||||
|         """) | ||||
|  | ||||
|     @property | ||||
|     def delete_string(self) -> str: | ||||
|         return str(f""" | ||||
|             DELETE FROM `UserJoinedVoiceChannel` | ||||
|             WHERE `JoinId` = {self._join_id}; | ||||
|         """) | ||||
							
								
								
									
										26
									
								
								src/bot_data/service/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/bot_data/service/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
|  | ||||
| """ | ||||
| bot-data Keksdose bot - data | ||||
| ~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| Discord bot  for the Keksdose discord Server - database package | ||||
|  | ||||
| :copyright: (c) 2022 sh-edraft.de | ||||
| :license: MIT, see LICENSE for more details. | ||||
|  | ||||
| """ | ||||
|  | ||||
| __title__ = 'bot_data.service' | ||||
| __author__ = 'Sven Heidemann' | ||||
| __license__ = 'MIT' | ||||
| __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||
| __version__ = '1.0.0.dev1' | ||||
|  | ||||
| from collections import namedtuple | ||||
|  | ||||
|  | ||||
| # imports | ||||
|  | ||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||
| version_info = VersionInfo(major='1', minor='0', micro='0.dev1') | ||||
							
								
								
									
										173
									
								
								src/bot_data/service/client_repository_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								src/bot_data/service/client_repository_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,173 @@ | ||||
| from typing import Optional | ||||
| from cpl_core.database.context import DatabaseContextABC | ||||
| from cpl_core.logging import LoggerABC | ||||
| from cpl_query.extension import List | ||||
|  | ||||
| from bot_data.abc.client_repository_abc import ClientRepositoryABC | ||||
| from bot_data.abc.server_repository_abc import ServerRepositoryABC | ||||
| from bot_data.model.client import Client | ||||
|  | ||||
|  | ||||
| class ClientRepositoryService(ClientRepositoryABC): | ||||
|  | ||||
|     def __init__(self, logger: LoggerABC, db_context: DatabaseContextABC, servers: ServerRepositoryABC): | ||||
|         self._logger = logger | ||||
|         self._context = db_context | ||||
|  | ||||
|         self._servers = servers | ||||
|  | ||||
|         ClientRepositoryABC.__init__(self) | ||||
|  | ||||
|     def get_clients(self) -> List[Client]: | ||||
|         clients = List(Client) | ||||
|         self._logger.trace(__name__, f'Send SQL command: {Client.get_select_all_string()}') | ||||
|         results = self._context.select(Client.get_select_all_string()) | ||||
|         for result in results: | ||||
|             self._logger.trace(__name__, f'Get client with id {result[0]}') | ||||
|             clients.append(Client( | ||||
|                 result[1], | ||||
|                 result[2], | ||||
|                 result[3], | ||||
|                 result[4], | ||||
|                 result[5], | ||||
|                 result[6], | ||||
|                 self._servers.get_server_by_id(result[7]), | ||||
|                 id=result[0] | ||||
|             )) | ||||
|  | ||||
|         return clients | ||||
|  | ||||
|     def get_client_by_id(self, client_id: int) -> Client: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {Client.get_select_by_id_string(client_id)}') | ||||
|         result = self._context.select(Client.get_select_by_id_string(client_id)) | ||||
|         return Client( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             result[3], | ||||
|             result[4], | ||||
|             result[5], | ||||
|             result[6], | ||||
|             self._servers.get_server_by_id(result[7]), | ||||
|             id=result[0] | ||||
|         ) | ||||
|  | ||||
|     def get_client_by_discord_id(self, discord_id: int) -> Client: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {Client.get_select_by_discord_id_string(discord_id)}') | ||||
|         result = self._context.select(Client.get_select_by_discord_id_string(discord_id))[0] | ||||
|         return Client( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             result[3], | ||||
|             result[4], | ||||
|             result[5], | ||||
|             result[6], | ||||
|             self._servers.get_server_by_id(result[7]), | ||||
|             id=result[0] | ||||
|         ) | ||||
|  | ||||
|     def find_client_by_discord_id(self, discord_id: int) -> Optional[Client]: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {Client.get_select_by_discord_id_string(discord_id)}') | ||||
|         result = self._context.select(Client.get_select_by_discord_id_string(discord_id)) | ||||
|         if result is None or len(result) == 0: | ||||
|             return None | ||||
|          | ||||
|         result = result[0] | ||||
|          | ||||
|         return Client( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             result[3], | ||||
|             result[4], | ||||
|             result[5], | ||||
|             result[6], | ||||
|             self._servers.get_server_by_id(result[7]), | ||||
|             id=result[0] | ||||
|         ) | ||||
|  | ||||
|     def find_client_by_server_id(self, discord_id: int) -> Optional[Client]: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {Client.get_select_by_server_id_string(discord_id)}') | ||||
|         result = self._context.select(Client.get_select_by_server_id_string(discord_id)) | ||||
|         if result is None or len(result) == 0: | ||||
|             return None | ||||
|          | ||||
|         result = result[0] | ||||
|          | ||||
|         return Client( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             result[3], | ||||
|             result[4], | ||||
|             result[5], | ||||
|             result[6], | ||||
|             self._servers.get_server_by_id(result[7]), | ||||
|             id=result[0] | ||||
|         ) | ||||
|  | ||||
|     def find_client_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> Optional[Client]: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {Client.get_select_by_discord_id_and_server_id_string(discord_id, server_id)}') | ||||
|         result = self._context.select(Client.get_select_by_discord_id_and_server_id_string(discord_id, server_id)) | ||||
|         if result is None or len(result) == 0: | ||||
|             return None | ||||
|          | ||||
|         result = result[0] | ||||
|          | ||||
|         return Client( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             result[3], | ||||
|             result[4], | ||||
|             result[5], | ||||
|             result[6], | ||||
|             self._servers.get_server_by_id(result[7]), | ||||
|             id=result[0] | ||||
|         ) | ||||
|      | ||||
|     def add_client(self, client: Client): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {client.insert_string}') | ||||
|         self._context.cursor.execute(client.insert_string) | ||||
|      | ||||
|     def update_client(self, client: Client): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {client.udpate_string}') | ||||
|         self._context.cursor.execute(client.udpate_string) | ||||
|      | ||||
|     def delete_client(self, client: Client): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {client.delete_string}') | ||||
|         self._context.cursor.execute(client.delete_string) | ||||
|  | ||||
|     def _get_client_and_server(self, id: int, server_id: int) -> Client: | ||||
|         server = self._servers.find_server_by_discord_id(server_id) | ||||
|         if server is None: | ||||
|             self._logger.warn(__name__, f'Cannot find server by id {server_id}') | ||||
|             raise Exception('Value not found') | ||||
|          | ||||
|         client = self.find_client_by_discord_id_and_server_id(id, server.server_id) | ||||
|         if client is None: | ||||
|             self._logger.warn(__name__, f'Cannot find client by ids {id}@{server.server_id}') | ||||
|             raise Exception('Value not found') | ||||
|          | ||||
|         return client | ||||
|  | ||||
|     def append_sent_message_count(self, client_id: int, server_id: int, value: int): | ||||
|         client = self._get_client_and_server(client_id, server_id) | ||||
|         client.sent_message_count += value | ||||
|         self.update_client(client) | ||||
|  | ||||
|     def append_received_message_count(self, client_id: int, server_id: int, value: int): | ||||
|         client = self._get_client_and_server(client_id, server_id) | ||||
|         client.received_message_count += value | ||||
|         self.update_client(client) | ||||
|  | ||||
|     def append_deleted_message_count(self, client_id: int, server_id: int, value: int): | ||||
|         client = self._get_client_and_server(client_id, server_id) | ||||
|         client.deleted_message_count += value | ||||
|         self.update_client(client) | ||||
|  | ||||
|     def append_received_command_count(self, client_id: int, server_id: int, value: int): | ||||
|         client = self._get_client_and_server(client_id, server_id) | ||||
|         client.received_command_count += value | ||||
|         self.update_client(client) | ||||
|  | ||||
|     def append_moved_users_count(self, client_id: int, server_id: int, value: int): | ||||
|         client = self._get_client_and_server(client_id, server_id) | ||||
|         client.moved_users_count += value | ||||
|         self.update_client(client) | ||||
							
								
								
									
										77
									
								
								src/bot_data/service/known_user_repository_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/bot_data/service/known_user_repository_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| from typing import Optional | ||||
| from cpl_core.database.context import DatabaseContextABC | ||||
| from cpl_core.logging import LoggerABC | ||||
| from cpl_query.extension import List | ||||
| from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC | ||||
|  | ||||
| from bot_data.abc.server_repository_abc import ServerRepositoryABC | ||||
| from bot_data.model.known_user import KnownUser | ||||
|  | ||||
|  | ||||
| class KnownUserRepositoryService(KnownUserRepositoryABC): | ||||
|  | ||||
|     def __init__(self, logger: LoggerABC, db_context: DatabaseContextABC, servers: ServerRepositoryABC): | ||||
|         self._logger = logger | ||||
|         self._context = db_context | ||||
|  | ||||
|         self._servers = servers | ||||
|  | ||||
|         KnownUserRepositoryABC.__init__(self) | ||||
|  | ||||
|     def get_users(self) -> List[KnownUser]: | ||||
|         users = List(KnownUser) | ||||
|         self._logger.trace(__name__, f'Send SQL command: {KnownUser.get_select_all_string()}') | ||||
|         results = self._context.select(KnownUser.get_select_all_string()) | ||||
|         for result in results: | ||||
|             self._logger.trace(__name__, f'Get known_user with id {result[0]}') | ||||
|             users.append(KnownUser( | ||||
|                 result[1], | ||||
|                 result[2], | ||||
|                 result[3], | ||||
|                 id=result[0] | ||||
|             )) | ||||
|  | ||||
|         return users | ||||
|  | ||||
|     def get_user_by_id(self, id: int) -> KnownUser: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {KnownUser.get_select_by_id_string(id)}') | ||||
|         result = self._context.select(KnownUser.get_select_by_id_string(id)) | ||||
|         return KnownUser( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             result[3], | ||||
|             id=result[0] | ||||
|         ) | ||||
|  | ||||
|     def get_user_by_discord_id(self, discord_id: int) -> KnownUser: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {KnownUser.get_select_by_discord_id_string(discord_id)}') | ||||
|         result = self._context.select(KnownUser.get_select_by_discord_id_string(discord_id))[0] | ||||
|         return KnownUser( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             result[3], | ||||
|             id=result[0] | ||||
|         ) | ||||
|  | ||||
|     def find_user_by_discord_id(self, discord_id: int) -> Optional[KnownUser]: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {KnownUser.get_select_by_discord_id_string(discord_id)}') | ||||
|         result = self._context.select(KnownUser.get_select_by_discord_id_string(discord_id)) | ||||
|         if result is None or len(result) == 0: | ||||
|             return None | ||||
|          | ||||
|         result = result[0] | ||||
|          | ||||
|         return KnownUser( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             result[3], | ||||
|             id=result[0] | ||||
|         ) | ||||
|      | ||||
|     def add_user(self, known_user: KnownUser): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {known_user.insert_string}') | ||||
|         self._context.cursor.execute(known_user.insert_string) | ||||
|      | ||||
|     def delete_user(self, known_user: KnownUser): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {known_user.delete_string}') | ||||
|         self._context.cursor.execute(known_user.delete_string) | ||||
							
								
								
									
										45
									
								
								src/bot_data/service/migration_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/bot_data/service/migration_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| from typing import Type | ||||
|  | ||||
| from cpl_core.database.context import DatabaseContextABC | ||||
| from cpl_core.dependency_injection import ServiceProviderABC | ||||
| from cpl_core.logging import LoggerABC | ||||
|  | ||||
| from bot_data.abc.migration_abc import MigrationABC | ||||
| from bot_data.model.migration_history import MigrationHistory | ||||
|  | ||||
|  | ||||
| class MigrationService: | ||||
|  | ||||
|     def __init__(self, logger: LoggerABC, services: ServiceProviderABC, db: DatabaseContextABC): | ||||
|         self._logger = logger | ||||
|         self._services = services | ||||
|          | ||||
|         self._db = db | ||||
|         self._cursor = db.cursor | ||||
|  | ||||
|         self._migrations: list[Type[MigrationABC]] = MigrationABC.__subclasses__() | ||||
|      | ||||
|     def migrate(self): | ||||
|         self._logger.info(__name__, f"Running Migrations") | ||||
|         for migration in self._migrations: | ||||
|             migration_id = migration.__name__ | ||||
|             try: | ||||
|                 # check if table exists | ||||
|                 self._cursor.execute("SHOW TABLES LIKE 'MigrationHistory'") | ||||
|                 result = self._cursor.fetchone() | ||||
|                 if result: | ||||
|                     # there is a table named "tableName" | ||||
|                     self._logger.trace(__name__, f"Running SQL Command: {MigrationHistory.get_select_by_id_string(migration_id)}") | ||||
|                     migration_from_db = self._db.select(MigrationHistory.get_select_by_id_string(migration_id)) | ||||
|                     self._logger.trace(__name__, str(migration_from_db)) | ||||
|                     if migration_from_db is not None and len(migration_from_db) > 0: | ||||
|                         continue | ||||
|                  | ||||
|                 self._logger.debug(__name__, f"Running Migration {migration}") | ||||
|                 migration_as_service: MigrationABC = self._services.get_service(migration) | ||||
|                 migration_as_service.upgrade() | ||||
|                 self._cursor.execute(MigrationHistory(migration_id).insert_string) | ||||
|                 self._db.save_changes() | ||||
|  | ||||
|             except Exception as e: | ||||
|                 self._logger.error(__name__, f'Cannot get migration with id {migration}', e) | ||||
							
								
								
									
										71
									
								
								src/bot_data/service/server_repository_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/bot_data/service/server_repository_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| from typing import Optional | ||||
| 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.model.server import Server | ||||
|  | ||||
|  | ||||
| class ServerRepositoryService(ServerRepositoryABC): | ||||
|  | ||||
|     def __init__(self, logger: LoggerABC, db_context: DatabaseContextABC): | ||||
|         self._logger = logger | ||||
|         self._context = db_context | ||||
|  | ||||
|         ServerRepositoryABC.__init__(self) | ||||
|  | ||||
|     def get_servers(self) -> List[Server]: | ||||
|         servers = List(Server) | ||||
|         self._logger.trace(__name__, f'Send SQL command: {Server.get_select_all_string()}') | ||||
|         results = self._context.select(Server.get_select_all_string()) | ||||
|         for result in results: | ||||
|             servers.append(Server( | ||||
|                 result[1], | ||||
|                 id=result[0] | ||||
|             )) | ||||
|  | ||||
|         return servers | ||||
|  | ||||
|     def get_server_by_id(self, server_id: int) -> Server: | ||||
|         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] | ||||
|         return Server( | ||||
|             result[1], | ||||
|             id=result[0] | ||||
|         ) | ||||
|  | ||||
|     def get_server_by_discord_id(self, discord_id: int) -> Server: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {Server.get_select_by_discord_id_string(discord_id)}') | ||||
|         result = self._context.select(Server.get_select_by_discord_id_string(discord_id))[0] | ||||
|         return Server( | ||||
|             result[1], | ||||
|             id=result[0] | ||||
|         ) | ||||
|  | ||||
|     def find_server_by_discord_id(self, discord_id: int) -> Optional[Server]: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {Server.get_select_by_discord_id_string(discord_id)}') | ||||
|         result = self._context.select(Server.get_select_by_discord_id_string(discord_id)) | ||||
|         if result is None or len(result) == 0: | ||||
|             return None | ||||
|          | ||||
|         result = result[0] | ||||
|          | ||||
|         return Server( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             result[3], | ||||
|             id=result[0] | ||||
|         ) | ||||
|      | ||||
|     def add_server(self, server: Server): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {server.insert_string}') | ||||
|         self._context.cursor.execute(server.insert_string) | ||||
|      | ||||
|     def update_server(self, server: Server): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {server.udpate_string}') | ||||
|         self._context.cursor.execute(server.udpate_string) | ||||
|      | ||||
|     def delete_server(self, server: Server): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {server.delete_string}') | ||||
|         self._context.cursor.execute(server.delete_string) | ||||
							
								
								
									
										107
									
								
								src/bot_data/service/user_joined_server_repository_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								src/bot_data/service/user_joined_server_repository_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,107 @@ | ||||
| from typing import Optional | ||||
|  | ||||
| from cpl_core.database.context import DatabaseContextABC | ||||
| from cpl_core.logging import LoggerABC | ||||
| from cpl_query.extension import List | ||||
| from bot_data.abc.user_joined_server_repository_abc import \ | ||||
|     UserJoinedServerRepositoryABC | ||||
| from bot_data.abc.user_repository_abc import UserRepositoryABC | ||||
| from bot_data.model.user import User | ||||
| from bot_data.model.user_joined_server import UserJoinedServer | ||||
|  | ||||
|  | ||||
| class UserJoinedServerRepositoryService(UserJoinedServerRepositoryABC): | ||||
|  | ||||
|     def __init__(self, logger: LoggerABC, db_context: DatabaseContextABC, users: UserRepositoryABC): | ||||
|         self._logger = logger | ||||
|         self._context = db_context | ||||
|  | ||||
|         self._users = users | ||||
|  | ||||
|         UserJoinedServerRepositoryABC.__init__(self) | ||||
|  | ||||
|     def get_user_joined_servers(self) -> List[UserJoinedServer]: | ||||
|         joins = List(UserJoinedServer) | ||||
|         self._logger.trace(__name__, f'Send SQL command: {UserJoinedServer.get_select_all_string()}') | ||||
|         results = self._context.select(UserJoinedServer.get_select_all_string()) | ||||
|         for result in results: | ||||
|             self._logger.trace(__name__, f'Get user-joined-server with id {result[0]}') | ||||
|             joins.append(UserJoinedServer( | ||||
|                 self._users.get_user_by_id(result[1]), | ||||
|                 result[2], | ||||
|                 result[3], | ||||
|                 result[4], | ||||
|                 result[5], | ||||
|                 id=result[0] | ||||
|             )) | ||||
|  | ||||
|         return joins | ||||
|      | ||||
|     def get_user_joined_server_by_id(self, id: int) -> UserJoinedServer: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {UserJoinedServer.get_select_by_id_string(id)}') | ||||
|         result = self._context.select(UserJoinedServer.get_select_by_id_string(id))[0] | ||||
|         return UserJoinedServer( | ||||
|             self._users.get_user_by_id(result[1]), | ||||
|             result[2], | ||||
|             result[3], | ||||
|             result[4], | ||||
|             result[5], | ||||
|             id=result[0] | ||||
|         ) | ||||
|      | ||||
|     def get_user_joined_servers_by_user_id(self, user_id: int) -> List[UserJoinedServer]: | ||||
|         joins = List(UserJoinedServer) | ||||
|         self._logger.trace(__name__, f'Send SQL command: {UserJoinedServer.get_select_by_user_id_string(user_id)}') | ||||
|         results = self._context.select(UserJoinedServer.get_select_by_user_id_string(user_id)) | ||||
|         for result in results: | ||||
|             joins.append(UserJoinedServer( | ||||
|                 self._users.get_user_by_id(result[1]), | ||||
|                 result[2], | ||||
|                 result[3], | ||||
|                 result[4], | ||||
|                 result[5], | ||||
|                 id=result[0] | ||||
|             )) | ||||
|      | ||||
|         return joins | ||||
|      | ||||
|     def get_active_user_joined_server_by_user_id(self, user_id: int) -> UserJoinedServer: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {UserJoinedServer.get_select_by_user_id_string(user_id)}') | ||||
|         result = self._context.select(UserJoinedServer.get_select_active_by_user_id_string(user_id))[0] | ||||
|         return UserJoinedServer( | ||||
|             self._users.get_user_by_id(result[1]), | ||||
|             result[2], | ||||
|             result[3], | ||||
|             result[4], | ||||
|             result[5], | ||||
|             id=result[0] | ||||
|         ) | ||||
|      | ||||
|     def find_active_user_joined_server_by_user_id(self, user_id: int) -> Optional[UserJoinedServer]: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {UserJoinedServer.get_select_by_user_id_string(user_id)}') | ||||
|         result = self._context.select(UserJoinedServer.get_select_active_by_user_id_string(user_id)) | ||||
|         if result is None or len(result) == 0: | ||||
|             return None | ||||
|  | ||||
|         result = result[0] | ||||
|  | ||||
|         return UserJoinedServer( | ||||
|             self._users.get_user_by_id(result[1]), | ||||
|             result[2], | ||||
|             result[3], | ||||
|             result[4], | ||||
|             result[5], | ||||
|             id=result[0] | ||||
|         ) | ||||
|      | ||||
|     def add_user_joined_server(self, user_joined_server: UserJoinedServer): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {user_joined_server.insert_string}') | ||||
|         self._context.cursor.execute(user_joined_server.insert_string) | ||||
|      | ||||
|     def update_user_joined_server(self, user_joined_server: UserJoinedServer): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {user_joined_server.udpate_string}') | ||||
|         self._context.cursor.execute(user_joined_server.udpate_string) | ||||
|      | ||||
|     def delete_user_joined_server(self, user_joined_server: UserJoinedServer): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {user_joined_server.delete_string}') | ||||
|         self._context.cursor.execute(user_joined_server.delete_string) | ||||
							
								
								
									
										123
									
								
								src/bot_data/service/user_joined_voice_channel_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								src/bot_data/service/user_joined_voice_channel_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | ||||
| from typing import Optional | ||||
|  | ||||
| from cpl_core.database.context import DatabaseContextABC | ||||
| from cpl_core.logging import LoggerABC | ||||
| from cpl_query.extension import List, IterableABC | ||||
| from bot_data.abc.user_repository_abc import UserRepositoryABC | ||||
| from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel | ||||
|  | ||||
| from bot_data.abc.user_joined_voice_channel_abc import UserJoinedVoiceChannelRepositoryABC | ||||
|  | ||||
|  | ||||
| class UserJoinedVoiceChannelRepositoryService(UserJoinedVoiceChannelRepositoryABC): | ||||
|  | ||||
|     def __init__(self, logger: LoggerABC, db_context: DatabaseContextABC, users: UserRepositoryABC): | ||||
|         self._logger = logger | ||||
|         self._context = db_context | ||||
|  | ||||
|         self._users = users | ||||
|  | ||||
|         UserJoinedVoiceChannelRepositoryABC.__init__(self) | ||||
|  | ||||
|     def get_user_joined_voice_channels(self) -> List[UserJoinedVoiceChannel]: | ||||
|         joins = List(UserJoinedVoiceChannel) | ||||
|         self._logger.trace(__name__, f'Send SQL command: {UserJoinedVoiceChannel.get_select_all_string()}') | ||||
|         results = self._context.select(UserJoinedVoiceChannel.get_select_all_string()) | ||||
|         for result in results: | ||||
|             self._logger.trace(__name__, f'Get user-joined-voice-channel with id {result[0]}') | ||||
|             joins.append(UserJoinedVoiceChannel( | ||||
|                 self._users.get_user_by_id(result[1]), | ||||
|                 result[2], | ||||
|                 result[3], | ||||
|                 result[4], | ||||
|                 result[5], | ||||
|                 id=result[0] | ||||
|             )) | ||||
|  | ||||
|         return joins | ||||
|      | ||||
|     def get_user_joined_voice_channel_by_id(self, id: int) -> UserJoinedVoiceChannel: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {UserJoinedVoiceChannel.get_select_by_id_string(id)}') | ||||
|         result = self._context.select(UserJoinedVoiceChannel.get_select_by_id_string(id))[0] | ||||
|         return UserJoinedVoiceChannel( | ||||
|             self._users.get_user_by_id(result[1]), | ||||
|             result[2], | ||||
|             result[3], | ||||
|             result[4], | ||||
|             result[5], | ||||
|             id=result[0] | ||||
|         ) | ||||
|      | ||||
|     def get_user_joined_voice_channels_by_user_id(self, user_id: int) -> List[UserJoinedVoiceChannel]: | ||||
|         joins = List(UserJoinedVoiceChannel) | ||||
|         self._logger.trace(__name__, f'Send SQL command: {UserJoinedVoiceChannel.get_select_by_user_id_string(user_id)}') | ||||
|         results = self._context.select(UserJoinedVoiceChannel.get_select_by_user_id_string(user_id)) | ||||
|         for result in results: | ||||
|             joins.append(UserJoinedVoiceChannel( | ||||
|                 self._users.get_user_by_id(result[1]), | ||||
|                 result[2], | ||||
|                 result[3], | ||||
|                 result[4], | ||||
|                 result[5], | ||||
|                 id=result[0] | ||||
|             )) | ||||
|      | ||||
|         return joins | ||||
|      | ||||
|     def get_active_user_joined_voice_channel_by_user_id(self, user_id: int) -> UserJoinedVoiceChannel: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {UserJoinedVoiceChannel.get_select_by_user_id_string(user_id)}') | ||||
|         result = self._context.select(UserJoinedVoiceChannel.get_select_active_by_user_id_string(user_id))[0] | ||||
|         return UserJoinedVoiceChannel( | ||||
|             self._users.get_user_by_id(result[1]), | ||||
|             result[2], | ||||
|             result[3], | ||||
|             result[4], | ||||
|             result[5], | ||||
|             id=result[0] | ||||
|         ) | ||||
|      | ||||
|     def find_active_user_joined_voice_channel_by_user_id(self, user_id: int) -> Optional[UserJoinedVoiceChannel]: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {UserJoinedVoiceChannel.get_select_by_user_id_string(user_id)}') | ||||
|         result = self._context.select(UserJoinedVoiceChannel.get_select_active_by_user_id_string(user_id)) | ||||
|         if result is None or len(result) == 0: | ||||
|             return None | ||||
|  | ||||
|         result = result[0] | ||||
|  | ||||
|         return UserJoinedVoiceChannel( | ||||
|             self._users.get_user_by_id(result[1]), | ||||
|             result[2], | ||||
|             result[3], | ||||
|             result[4], | ||||
|             result[5], | ||||
|             id=result[0] | ||||
|         ) | ||||
|  | ||||
|     def find_active_user_joined_voice_channels_by_user_id(self, user_id: int) -> List[Optional[UserJoinedVoiceChannel]]: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {UserJoinedVoiceChannel.get_select_by_user_id_string(user_id)}') | ||||
|         result = List(UserJoinedVoiceChannel) | ||||
|         db_results = self._context.select(UserJoinedVoiceChannel.get_select_active_by_user_id_string(user_id)) | ||||
|  | ||||
|         for db_result in db_results: | ||||
|             result.append(UserJoinedVoiceChannel( | ||||
|                 self._users.get_user_by_id(db_result[1]), | ||||
|                 db_result[2], | ||||
|                 db_result[3], | ||||
|                 db_result[4], | ||||
|                 db_result[5], | ||||
|                 id=db_result[0] | ||||
|             )) | ||||
|  | ||||
|         return result | ||||
|      | ||||
|     def add_user_joined_voice_channel(self, user_joined_voice_channel: UserJoinedVoiceChannel): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {user_joined_voice_channel.insert_string}') | ||||
|         self._context.cursor.execute(user_joined_voice_channel.insert_string) | ||||
|      | ||||
|     def update_user_joined_voice_channel(self, user_joined_voice_channel: UserJoinedVoiceChannel): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {user_joined_voice_channel.udpate_string}') | ||||
|         self._context.cursor.execute(user_joined_voice_channel.udpate_string) | ||||
|      | ||||
|     def delete_user_joined_voice_channel(self, user_joined_voice_channel: UserJoinedVoiceChannel): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {user_joined_voice_channel.delete_string}') | ||||
|         self._context.cursor.execute(user_joined_voice_channel.delete_string) | ||||
							
								
								
									
										99
									
								
								src/bot_data/service/user_repository_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								src/bot_data/service/user_repository_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | ||||
| from typing import Optional | ||||
| 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 bot_data.model.user import User | ||||
|  | ||||
|  | ||||
| class UserRepositoryService(UserRepositoryABC): | ||||
|  | ||||
|     def __init__(self, logger: LoggerABC, db_context: DatabaseContextABC, servers: ServerRepositoryABC): | ||||
|         self._logger = logger | ||||
|         self._context = db_context | ||||
|  | ||||
|         self._servers = servers | ||||
|  | ||||
|         UserRepositoryABC.__init__(self) | ||||
|  | ||||
|     def get_users(self) -> List[User]: | ||||
|         users = List(User) | ||||
|         self._logger.trace(__name__, f'Send SQL command: {User.get_select_all_string()}') | ||||
|         results = self._context.select(User.get_select_all_string()) | ||||
|         for result in results: | ||||
|             self._logger.trace(__name__, f'Get user with id {result[0]}') | ||||
|             users.append(User( | ||||
|                 result[1], | ||||
|                 result[2], | ||||
|                 self._servers.get_server_by_id(result[3]), | ||||
|                 id=result[0] | ||||
|             )) | ||||
|  | ||||
|         return users | ||||
|  | ||||
|     def get_user_by_id(self, id: int) -> User: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {User.get_select_by_id_string(id)}') | ||||
|         result = self._context.select(User.get_select_by_id_string(id))[0] | ||||
|  | ||||
|         return User( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             self._servers.get_server_by_id(result[3]), | ||||
|             id=result[0] | ||||
|         ) | ||||
|      | ||||
|     def get_users_by_discord_id(self, discord_id: int) -> List[User]: | ||||
|         users = List(User) | ||||
|         self._logger.trace(__name__, f'Send SQL command: {User.get_select_by_discord_id_string(discord_id)}') | ||||
|         results = self._context.select(User.get_select_by_discord_id_string(discord_id)) | ||||
|         for result in results: | ||||
|             users.append(User( | ||||
|                 result[1], | ||||
|                 result[2], | ||||
|                 self._servers.get_server_by_id(result[3]), | ||||
|                 id=result[0] | ||||
|             )) | ||||
|  | ||||
|         return users | ||||
|  | ||||
|     def get_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> User: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {User.get_select_by_discord_id_and_server_id_string(discord_id, server_id)}') | ||||
|         result = self._context.select(User.get_select_by_discord_id_and_server_id_string(discord_id, server_id))[0] | ||||
|          | ||||
|         return User( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             self._servers.get_server_by_id(result[3]), | ||||
|             id=result[0] | ||||
|         ) | ||||
|  | ||||
|     def find_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> Optional[User]: | ||||
|         self._logger.trace(__name__, f'Send SQL command: {User.get_select_by_discord_id_and_server_id_string(discord_id, server_id)}') | ||||
|         result = self._context.select(User.get_select_by_discord_id_and_server_id_string(discord_id, server_id)) | ||||
|         if result is None or len(result) == 0: | ||||
|             return None | ||||
|          | ||||
|         result = result[0] | ||||
|          | ||||
|         return User( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             self._servers.get_server_by_id(result[3]), | ||||
|             result[4], | ||||
|             result[5], | ||||
|             id=result[0] | ||||
|         ) | ||||
|      | ||||
|     def add_user(self, user: User): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {user.insert_string}') | ||||
|         self._context.cursor.execute(user.insert_string) | ||||
|      | ||||
|     def update_user(self, user: User): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {user.udpate_string}') | ||||
|         self._context.cursor.execute(user.udpate_string) | ||||
|      | ||||
|     def delete_user(self, user: User): | ||||
|         self._logger.trace(__name__, f'Send SQL command: {user.delete_string}') | ||||
|         self._context.cursor.execute(user.delete_string) | ||||
							
								
								
									
										1
									
								
								src/modules/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| # imports | ||||
							
								
								
									
										1
									
								
								src/modules/base/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/base/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| # imports | ||||
							
								
								
									
										0
									
								
								src/modules/base/abc/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/modules/base/abc/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										12
									
								
								src/modules/base/abc/base_helper_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/modules/base/abc/base_helper_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| 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 | ||||
							
								
								
									
										46
									
								
								src/modules/base/base.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/modules/base/base.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| { | ||||
|   "ProjectSettings": { | ||||
|     "Name": "base", | ||||
|     "Version": { | ||||
|       "Major": "0", | ||||
|       "Minor": "0", | ||||
|       "Micro": "0" | ||||
|     }, | ||||
|     "Author": "", | ||||
|     "AuthorEmail": "", | ||||
|     "Description": "", | ||||
|     "LongDescription": "", | ||||
|     "URL": "", | ||||
|     "CopyrightDate": "", | ||||
|     "CopyrightName": "", | ||||
|     "LicenseName": "", | ||||
|     "LicenseDescription": "", | ||||
|     "Dependencies": [ | ||||
|       "cpl-core>=2022.7.0.post2" | ||||
|     ], | ||||
|     "DevDependencies": [ | ||||
|       "cpl-cli>=2022.7.0.post2" | ||||
|     ], | ||||
|     "PythonVersion": ">=3.10.4", | ||||
|     "PythonPath": { | ||||
|       "linux": "" | ||||
|     }, | ||||
|     "Classifiers": [] | ||||
|   }, | ||||
|   "BuildSettings": { | ||||
|     "ProjectType": "library", | ||||
|     "SourcePath": "", | ||||
|     "OutputPath": "../../dist", | ||||
|     "Main": "base.main", | ||||
|     "EntryPoint": "base", | ||||
|     "IncludePackageData": false, | ||||
|     "Included": [], | ||||
|     "Excluded": [ | ||||
|       "*/__pycache__", | ||||
|       "*/logs", | ||||
|       "*/tests" | ||||
|     ], | ||||
|     "PackageData": {}, | ||||
|     "ProjectReferences": [] | ||||
|   } | ||||
| } | ||||
							
								
								
									
										25
									
								
								src/modules/base/command/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/modules/base/command/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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__ = 'modules.base.service' | ||||
| __author__ = 'Sven Heidemann' | ||||
| __license__ = 'MIT' | ||||
| __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' | ||||
| __version__ = '0.4.2' | ||||
|  | ||||
| from collections import namedtuple | ||||
|  | ||||
| # imports | ||||
|  | ||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||
| version_info = VersionInfo(major='0', minor='4', micro='2') | ||||
							
								
								
									
										65
									
								
								src/modules/base/command/afk_command.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/modules/base/command/afk_command.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| from cpl_core.configuration import ConfigurationABC | ||||
| from cpl_core.database.context import DatabaseContext | ||||
| from cpl_core.logging import LoggerABC | ||||
| from cpl_discord.command import DiscordCommandABC | ||||
| from cpl_discord.service import DiscordBotServiceABC | ||||
| from cpl_translation import TranslatePipe | ||||
| from discord import VoiceChannel | ||||
| 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.configuration.server_settings import ServerSettings | ||||
| from bot_data.abc.client_repository_abc import ClientRepositoryABC | ||||
| from modules.base.configuration.base_server_settings import BaseServerSettings | ||||
|  | ||||
|  | ||||
| class AFKCommand(DiscordCommandABC): | ||||
|  | ||||
|     def __init__( | ||||
|             self, | ||||
|             logger: LoggerABC, | ||||
|             config: ConfigurationABC, | ||||
|             message_service: MessageServiceABC, | ||||
|             clients: ClientRepositoryABC, | ||||
|             db: DatabaseContext, | ||||
|             bot: DiscordBotServiceABC, | ||||
|             client_utils: ClientUtilsServiceABC, | ||||
|             translate: TranslatePipe | ||||
|     ): | ||||
|         DiscordCommandABC.__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._t = translate | ||||
|  | ||||
|         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: BaseServerSettings = self._config.get_configuration(f'BaseServerSettings_{ctx.guild.id}') | ||||
|         server_settings: ServerSettings = self._config.get_configuration(f'ServerSettings_{ctx.guild.id}') | ||||
|  | ||||
|         if ctx.author.voice is None or ctx.author.voice.channel is None: | ||||
|             await self._message_service.send_ctx_msg(ctx, self._t.transform('modules.base.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, self._t.transform('modules.base.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, self._t.transform('common.no_permission_message')) | ||||
|  | ||||
|         self._logger.trace(__name__, f'Finished afk command') | ||||
							
								
								
									
										40
									
								
								src/modules/base/command/help_command.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/modules/base/command/help_command.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| from cpl_core.configuration import ConfigurationABC | ||||
| 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.abc.client_utils_service_abc import ClientUtilsServiceABC | ||||
| from bot_core.abc.message_service_abc import MessageServiceABC | ||||
| from modules.base.configuration.base_server_settings import BaseServerSettings | ||||
|  | ||||
|  | ||||
| class HelpCommand(DiscordCommandABC): | ||||
|  | ||||
|     def __init__( | ||||
|             self, | ||||
|             config: ConfigurationABC, | ||||
|             logger: LoggerABC, | ||||
|             message_service: MessageServiceABC, | ||||
|             bot: DiscordBotServiceABC, | ||||
|             client_utils: ClientUtilsServiceABC | ||||
|     ): | ||||
|         DiscordCommandABC.__init__(self) | ||||
|  | ||||
|         self._config = config | ||||
|         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 help(self, ctx: Context, persistent_flag: str = None): | ||||
|         self._logger.debug(__name__, f'Received command help {ctx}:{persistent_flag}') | ||||
|         self._client_utils.received_command(ctx.guild.id) | ||||
|         settings: BaseServerSettings = self._config.get_configuration(f'BaseServerSettings_{ctx.guild.id}') | ||||
|         is_persistent = persistent_flag == '--stay' | ||||
|         await self._message_service.send_ctx_msg(ctx, settings.help_command_reference_url, is_persistent=is_persistent) | ||||
|         self._logger.trace(__name__, f'Finished help command') | ||||
							
								
								
									
										94
									
								
								src/modules/base/command/info_command_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								src/modules/base/command/info_command_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| from datetime import datetime | ||||
|  | ||||
| from cpl_core.configuration import ConfigurationABC | ||||
| from cpl_core.logging import LoggerABC | ||||
| from cpl_discord.command import DiscordCommandABC | ||||
| from cpl_discord.service import DiscordBotServiceABC | ||||
| from cpl_query.extension import List | ||||
| from discord.ext import commands | ||||
| from discord.ext.commands import Context | ||||
|  | ||||
| import bot | ||||
| from bot_core.abc.client_utils_service_abc import ClientUtilsServiceABC | ||||
| from bot_core.abc.message_service_abc import MessageServiceABC | ||||
| from modules.base.configuration.base_server_settings import BaseServerSettings | ||||
|  | ||||
|  | ||||
| class InfoCommandService(DiscordCommandABC): | ||||
|  | ||||
|     def __init__( | ||||
|             self, | ||||
|             config: ConfigurationABC, | ||||
|             logger: LoggerABC, | ||||
|             message_service: MessageServiceABC, | ||||
|             bot: DiscordBotServiceABC, | ||||
|             client_utils: ClientUtilsServiceABC | ||||
|     ): | ||||
|         DiscordCommandABC.__init__(self) | ||||
|  | ||||
|         self._config = config | ||||
|         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 info(self, ctx: Context): | ||||
|         # | ||||
|         # Todo: Use native embeds!!! | ||||
|         # | ||||
|         self._logger.debug(__name__, f'Received command info {ctx}') | ||||
|         self._client_utils.received_command(ctx.guild.id) | ||||
|         client = self._client_utils.get_client(self._bot.user.id, ctx.guild.id) | ||||
|         settings: BaseServerSettings = self._config.get_configuration(f'BaseServerSettings_{ctx.guild.id}') | ||||
|  | ||||
|         embed_description = EmbedDescription( | ||||
|             settings.info_command_message.embed_description.title, | ||||
|             settings.info_command_message.embed_description.description, | ||||
|             settings.info_command_message.embed_description.url, | ||||
|             settings.info_command_message.embed_description.color, | ||||
|             List(EmbedDescriptionField), | ||||
|             settings.info_command_message.embed_description.footer | ||||
|         ) | ||||
|  | ||||
|         for i in range(len(settings.info_command_message.embed_description.fields)): | ||||
|             settings_field = settings.info_command_message.embed_description.fields[i] | ||||
|             field = EmbedDescriptionField(settings_field.name, settings_field.value, settings_field.inline) | ||||
|  | ||||
|             if settings_field.value == '$version': | ||||
|                 field.value = bot.__version__ | ||||
|  | ||||
|             elif settings_field.value == '$ontime': | ||||
|                 start_time = self._config.get_configuration('Bot_StartTime') | ||||
|                 ontime = round((datetime.now() - datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S.%f')).total_seconds()/3600, 2) | ||||
|                 field.value = f'{ontime}h' | ||||
|  | ||||
|             elif settings_field.value == '$sent_message_count': | ||||
|                 field.value = client.sent_message_count | ||||
|  | ||||
|             elif settings_field.value == '$received_message_count': | ||||
|                 field.value = client.received_message_count | ||||
|  | ||||
|             elif settings_field.value == '$deleted_message_count': | ||||
|                 field.value = client.deleted_message_count | ||||
|  | ||||
|             elif settings_field.value == '$received_command_count': | ||||
|                 field.value = client.received_command_count | ||||
|  | ||||
|             elif settings_field.value == '$moved_users_count': | ||||
|                 field.value = client.moved_users_count | ||||
|  | ||||
|             elif settings_field.value == '$modules': | ||||
|                 field.value = '' | ||||
|                 for module in ModuleABC.__subclasses__(): | ||||
|                     field.value += f'{module.__name__}\n' | ||||
|  | ||||
|             embed_description.fields.append(field) | ||||
|  | ||||
|         await self._message_service.send_ctx_msg( | ||||
|             ctx, | ||||
|             EmbedService.get_embed(embed_description) | ||||
|         ) | ||||
|         self._logger.trace(__name__, f'Finished info command') | ||||
							
								
								
									
										37
									
								
								src/modules/base/command/ping_command.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/modules/base/command/ping_command.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| from cpl_core.logging import LoggerABC | ||||
| 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.client_utils_service_abc import ClientUtilsServiceABC | ||||
| from bot_core.abc.message_service_abc import MessageServiceABC | ||||
|  | ||||
|  | ||||
| class PingCommand(DiscordCommandABC): | ||||
|  | ||||
|     def __init__( | ||||
|             self, | ||||
|             logger: LoggerABC, | ||||
|             message_service: MessageServiceABC, | ||||
|             bot: DiscordBotServiceABC, | ||||
|             client_utils: ClientUtilsServiceABC, | ||||
|             translate: TranslatePipe | ||||
|     ): | ||||
|         DiscordCommandABC.__init__(self) | ||||
|  | ||||
|         self._logger = logger | ||||
|         self._message_service = message_service | ||||
|         self._bot = bot | ||||
|         self._client_utils = client_utils | ||||
|         self._t = translate | ||||
|  | ||||
|         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, self._t.transform('modules.base.pong')) | ||||
|         self._logger.trace(__name__, f'Finished ping command') | ||||
							
								
								
									
										58
									
								
								src/modules/base/command/purge_command.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/modules/base/command/purge_command.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| import asyncio | ||||
|  | ||||
| from cpl_core.configuration import ConfigurationABC | ||||
| from cpl_core.logging import LoggerABC | ||||
| from cpl_discord.command import DiscordCommandABC | ||||
| 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.configuration.server_settings import ServerSettings | ||||
| from modules.permission.abc.permission_service_abc import PermissionServiceABC | ||||
|  | ||||
|  | ||||
| class PurgeCommand(DiscordCommandABC): | ||||
|  | ||||
|     def __init__( | ||||
|             self, | ||||
|             logger: LoggerABC, | ||||
|             config: ConfigurationABC, | ||||
|             message_service: MessageServiceABC, | ||||
|             permissions: PermissionServiceABC, | ||||
|             client_utils: ClientUtilsServiceABC, | ||||
|             translate: TranslatePipe | ||||
|     ): | ||||
|         DiscordCommandABC.__init__(self) | ||||
|  | ||||
|         self._logger = logger | ||||
|         self._config = config | ||||
|         self._message_service = message_service | ||||
|         self._permissions = permissions | ||||
|         self._client_utils = client_utils | ||||
|         self._t = translate | ||||
|  | ||||
|         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) | ||||
|  | ||||
|         server_settings: ServerSettings = self._config.get_configuration(f'ServerSettings_{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 purge command') | ||||
|             return | ||||
|  | ||||
|         await self._message_service.send_ctx_msg(ctx, self._t.transform('modules.base.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, self._t.transform('common.bot_has_no_permission_message')) | ||||
|  | ||||
|         self._logger.trace(__name__, f'Finished purge command') | ||||
							
								
								
									
										130
									
								
								src/modules/base/command/user_info_command_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								src/modules/base/command/user_info_command_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,130 @@ | ||||
| from typing import Optional | ||||
|  | ||||
| import discord | ||||
| from cpl_core.configuration import ConfigurationABC | ||||
| from cpl_core.logging import LoggerABC | ||||
| from cpl_discord.command import DiscordCommandABC | ||||
| from cpl_discord.service import DiscordBotServiceABC | ||||
| from cpl_query.extension import List | ||||
| 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_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.configuration.base_server_settings import BaseServerSettings | ||||
| from modules.permission.abc.permission_service_abc import PermissionServiceABC | ||||
|  | ||||
|  | ||||
| class UserInfoCommandService(DiscordCommandABC): | ||||
|  | ||||
|     def __init__( | ||||
|             self, | ||||
|             config: ConfigurationABC, | ||||
|             logger: LoggerABC, | ||||
|             message_service: MessageServiceABC, | ||||
|             bot: DiscordBotServiceABC, | ||||
|             client_utils: ClientUtilsServiceABC, | ||||
|             permissions: PermissionServiceABC, | ||||
|             servers: ServerRepositoryABC, | ||||
|             users: UserRepositoryABC, | ||||
|             user_joined_servers: UserJoinedServerRepositoryABC | ||||
|     ): | ||||
|         DiscordCommandABC.__init__(self) | ||||
|  | ||||
|         self._config = config | ||||
|         self._logger = logger | ||||
|         self._message_service = message_service | ||||
|         self._bot = bot | ||||
|         self._client_utils = client_utils | ||||
|         self._permissions = permissions | ||||
|         self._servers = servers | ||||
|         self._users = users | ||||
|         self._user_joined_servers = user_joined_servers | ||||
|  | ||||
|         self._logger.trace(__name__, f'Loaded command service: {type(self).__name__}') | ||||
|  | ||||
|     @commands.command(name='user-info') | ||||
|     async def user_info(self, ctx: Context, member: Optional[discord.Member] = None, *, wait: int = None): | ||||
|         # | ||||
|         # Todo: Use native embeds!!! | ||||
|         # | ||||
|         self._logger.debug(__name__, f'Received command user-info {ctx}:{member},{wait}') | ||||
|         self._client_utils.received_command(ctx.guild.id) | ||||
|         settings: BaseServerSettings = self._config.get_configuration(f'BaseServerSettings_{ctx.guild.id}') | ||||
|  | ||||
|         if not self._permissions.is_member_moderator(ctx.author): | ||||
|             await self._message_service.send_ctx_msg(ctx, settings.no_permission_message) | ||||
|             self._logger.trace(__name__, f'Finished purge command') | ||||
|             return | ||||
|  | ||||
|         if member is None or not isinstance(member, discord.Member): | ||||
|             member = ctx.author | ||||
|  | ||||
|         server = self._servers.find_server_by_discord_id(ctx.guild.id) | ||||
|         user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) | ||||
|         joins = self._user_joined_servers.get_user_joined_servers_by_user_id(user.user_id) | ||||
|  | ||||
|         embed_description = EmbedDescription( | ||||
|             settings.user_info_command_message.embed_description.title.format(member.name), | ||||
|             settings.user_info_command_message.embed_description.description.format(member.name), | ||||
|             settings.user_info_command_message.embed_description.url, | ||||
|             settings.user_info_command_message.embed_description.color, | ||||
|             List(EmbedDescriptionField), | ||||
|             settings.user_info_command_message.embed_description.footer | ||||
|         ) | ||||
|  | ||||
|         for i in range(len(settings.user_info_command_message.embed_description.fields)): | ||||
|             settings_field = settings.user_info_command_message.embed_description.fields[i] | ||||
|             field = EmbedDescriptionField(settings_field.name, settings_field.value, settings_field.inline) | ||||
|  | ||||
|             if settings_field.value == '$id': | ||||
|                 field.value = settings_field.value.replace('$id', str(member.id)) | ||||
|  | ||||
|             elif settings_field.value == '$name': | ||||
|                 field.value = settings_field.value.replace('$name', member.name) | ||||
|  | ||||
|             elif settings_field.value == '$discord_join': | ||||
|                 field.value = settings_field.value.replace('$discord_join', str(member.created_at)) | ||||
|  | ||||
|             elif settings_field.value == '$last_join': | ||||
|                 field.value = settings_field.value.replace('$last_join', str(member.joined_at)) | ||||
|  | ||||
|             elif settings_field.value == '$xp': | ||||
|                 field.value = settings_field.value.replace('$xp', str(user.xp)) | ||||
|  | ||||
|             elif settings_field.value == '$roles': | ||||
|                 roles = '' | ||||
|                 for role in member.roles: | ||||
|                     roles += f'{role.name}\n' | ||||
|                 field.value = settings_field.value.replace('$roles', roles) | ||||
|  | ||||
|             elif settings_field.value == '$joins': | ||||
|                 joins_string = '' | ||||
|                 for join in joins: | ||||
|                     joins_string += f'{join.joined_on}\n' | ||||
|                 field.value = settings_field.value.replace('$joins', joins_string) | ||||
|  | ||||
|             elif settings_field.value == '$leavings': | ||||
|                 leavings_string = '' | ||||
|                 for join in joins: | ||||
|                     if join.leaved_on is None: | ||||
|                         if leavings_string == '': | ||||
|                             leavings_string = '/' | ||||
|                         continue | ||||
|                     leavings_string += f'{join.leaved_on}\n' | ||||
|                 field.value = settings_field.value.replace('$leavings', leavings_string) | ||||
|  | ||||
|             elif settings_field.value == '$warnings': | ||||
|                 field.value = 'Not Implemented yet' | ||||
|  | ||||
|             embed_description.fields.append(field) | ||||
|  | ||||
|         await self._message_service.send_ctx_msg( | ||||
|             ctx, | ||||
|             EmbedService.get_embed(embed_description), | ||||
|             wait_before_delete=wait | ||||
|         ) | ||||
|         self._logger.trace(__name__, f'Finished user-info command') | ||||
							
								
								
									
										0
									
								
								src/modules/base/configuration/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/modules/base/configuration/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										58
									
								
								src/modules/base/configuration/base_server_settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/modules/base/configuration/base_server_settings.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| import traceback | ||||
|  | ||||
| from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC | ||||
| from cpl_core.console import Console | ||||
|  | ||||
|  | ||||
| class BaseServerSettings(ConfigurationModelABC): | ||||
|  | ||||
|     def __init__(self): | ||||
|         ConfigurationModelABC.__init__(self) | ||||
|  | ||||
|         self._id: int = 0 | ||||
|         self._max_voice_state_hours: int = 0 | ||||
|         self._xp_per_message: int = 0 | ||||
|         self._xp_per_ontime_hour: int = 0 | ||||
|         self._afk_channel_ids: list[int] = [] | ||||
|  | ||||
|     @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_ontime_hour(self) -> int: | ||||
|         return self._xp_per_ontime_hour | ||||
|  | ||||
|     @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 | ||||
|  | ||||
|     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_ontime_hour = int(settings['XpPerOntimeHour']) | ||||
|             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'] | ||||
|         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()}') | ||||
							
								
								
									
										32
									
								
								src/modules/base/configuration/base_settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/modules/base/configuration/base_settings.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| import traceback | ||||
|  | ||||
| from cpl_core.configuration import ConfigurationModelABC | ||||
| from cpl_core.console import Console | ||||
| from cpl_query.extension import List | ||||
|  | ||||
| from modules.base.configuration.base_server_settings import BaseServerSettings | ||||
|  | ||||
|  | ||||
| class BaseSettings(ConfigurationModelABC): | ||||
|  | ||||
|     def __init__(self): | ||||
|         ConfigurationModelABC.__init__(self) | ||||
|  | ||||
|         self._servers: List[BaseServerSettings] = List() | ||||
|      | ||||
|     @property | ||||
|     def servers(self) -> List[BaseServerSettings]: | ||||
|         return self._servers | ||||
|  | ||||
|     def from_dict(self, settings: dict): | ||||
|         try: | ||||
|             servers = List(BaseServerSettings) | ||||
|             for s in settings: | ||||
|                 st = BaseServerSettings() | ||||
|                 settings[s]['Id'] = s | ||||
|                 st.from_dict(settings[s]) | ||||
|                 servers.append(st) | ||||
|             self._servers = servers | ||||
|         except Exception as e: | ||||
|             Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings') | ||||
|             Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') | ||||
							
								
								
									
										0
									
								
								src/modules/base/events/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/modules/base/events/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										97
									
								
								src/modules/base/events/base_on_member_join_event.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/modules/base/events/base_on_member_join_event.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| 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 OnMemberJoinABC | ||||
| from cpl_translation import TranslatePipe | ||||
|  | ||||
| from bot_core.abc.message_service_abc import MessageServiceABC | ||||
| from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC | ||||
| 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.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 | ||||
|  | ||||
|  | ||||
| class BaseOnMemberJoinEvent(OnMemberJoinABC): | ||||
|  | ||||
|     def __init__( | ||||
|             self, | ||||
|             config: ConfigurationABC, | ||||
|             logger: LoggerABC, | ||||
|             base_helper: BaseHelperABC, | ||||
|             messenger: MessageServiceABC, | ||||
|             permissions: PermissionServiceABC, | ||||
|             db: DatabaseContextABC, | ||||
|             known_users: KnownUserRepositoryABC, | ||||
|             users: UserRepositoryABC, | ||||
|             servers: ServerRepositoryABC, | ||||
|             user_joins: UserJoinedServerRepositoryABC, | ||||
|             translate: TranslatePipe | ||||
|     ): | ||||
|         OnMemberJoinABC.__init__(self) | ||||
|         self._config = config | ||||
|         self._logger = logger | ||||
|         self._base_helper = base_helper | ||||
|         self._messenger = messenger | ||||
|         self._permission_service = permissions | ||||
|         self._db = db | ||||
|         self._known_users = known_users | ||||
|         self._users = users | ||||
|         self._servers = servers | ||||
|         self._user_joins = user_joins | ||||
|         self._t = translate | ||||
|  | ||||
|     def _check_for_known_user(self, member: Union[discord.User, discord.Member]): | ||||
|         self._logger.debug(__name__, f'Check if user is already known {member}') | ||||
|         try: | ||||
|             user = self._known_users.find_user_by_discord_id(member.id) | ||||
|             if user is not None: | ||||
|                 return | ||||
|  | ||||
|             self._logger.debug(__name__, f'Add user: {member.id}') | ||||
|             self._known_users.add_user(KnownUser(member.id)) | ||||
|             self._db.save_changes() | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f'Cannot get user {member.id}', e) | ||||
|  | ||||
|     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) | ||||
|  | ||||
|         for admin in self._permission_service.get_admins(member.guild.id): | ||||
|             await self._messenger.send_dm_message(self._t.transform('modules.base.welcome_message_for_team').format(member.name), admin) | ||||
|  | ||||
|         for moderator in self._permission_service.get_moderators(member.guild.id): | ||||
|             await self._messenger.send_dm_message(self._t.transform('modules.base.welcome_message_for_team').format(member.name), moderator) | ||||
|  | ||||
|         try: | ||||
|             server = self._servers.get_server_by_discord_id(member.guild.id) | ||||
|  | ||||
|             user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) | ||||
|             if user is not None: | ||||
|                 self._user_joins.add_user_joined_server(UserJoinedServer(user, datetime.now())) | ||||
|                 return | ||||
|  | ||||
|             self._logger.debug(__name__, f'Add user: {member.id}') | ||||
|             self._users.add_user(User(member.id, 0, server)) | ||||
|             self._db.save_changes() | ||||
|             user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) | ||||
|             self._user_joins.add_user_joined_server(UserJoinedServer(user, datetime.now())) | ||||
|             self._db.save_changes() | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f'Cannot get user {member.id}', e) | ||||
|  | ||||
|     async def on_member_join(self, member: discord.Member): | ||||
|         self._logger.debug(__name__, f'Module {type(self)} started') | ||||
|         self._check_for_known_user(member) | ||||
|         await self._add_if_not_exists_user_async(member) | ||||
							
								
								
									
										64
									
								
								src/modules/base/events/base_on_member_remove_event.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								src/modules/base/events/base_on_member_remove_event.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| from datetime import datetime | ||||
| from typing import Union | ||||
|  | ||||
| import discord | ||||
| from cpl_core.database.context import DatabaseContextABC | ||||
| from cpl_core.logging import LoggerABC | ||||
| from cpl_discord.events import OnMemberRemoveABC | ||||
| from cpl_translation import TranslatePipe | ||||
|  | ||||
| from bot_core.abc.message_service_abc import MessageServiceABC | ||||
| 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, | ||||
|             servers: ServerRepositoryABC, | ||||
|             user_joins: UserJoinedServerRepositoryABC, | ||||
|             translate: TranslatePipe | ||||
|     ): | ||||
|         OnMemberRemoveABC.__init__(self) | ||||
|  | ||||
|         self._logger = logger | ||||
|         self._base_helper = base_helper | ||||
|         self._db = db | ||||
|         self._messenger = messenger | ||||
|         self._users = users | ||||
|         self._servers = servers | ||||
|         self._user_joins = user_joins | ||||
|         self._t = translate | ||||
|  | ||||
|     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) | ||||
|         await self._messenger.send_dm_message(self._t.transform('modules.base.goodbye_message'), member) | ||||
|  | ||||
|         try: | ||||
|             server = self._servers.get_server_by_discord_id(member.guild.id) | ||||
|  | ||||
|             user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) | ||||
|             if user is None: | ||||
|                 self._logger.error(__name__, f'Cannot find user {member}') | ||||
|                 return | ||||
|  | ||||
|             join = self._user_joins.get_active_user_joined_server_by_user_id(user.user_id) | ||||
|             join.leaved_on = datetime.now() | ||||
|             self._user_joins.update_user_joined_server(join) | ||||
|             self._db.save_changes() | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f'Cannot get user {member.id}', e) | ||||
|  | ||||
|     async def on_member_remove(self, member: discord.Member): | ||||
|         self._logger.debug(__name__, f'Module {type(self)} started') | ||||
|         await self._remove_user(member) | ||||
							
								
								
									
										79
									
								
								src/modules/base/events/base_on_message_event.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/modules/base/events/base_on_message_event.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| from typing import Optional | ||||
|  | ||||
| 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_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 BaseOnMessageEvent(OnMessageABC): | ||||
|  | ||||
|     def __init__( | ||||
|             self, | ||||
|             logger: LoggerABC, | ||||
|             bhs: BaseHelperABC, | ||||
|             db: DatabaseContextABC, | ||||
|             bot: DiscordBotServiceABC, | ||||
|             users: UserRepositoryABC, | ||||
|             clients: ClientRepositoryABC, | ||||
|             servers: ServerRepositoryABC, | ||||
|     ): | ||||
|         OnMessageABC.__init__(self) | ||||
|         self._logger = logger | ||||
|         self._base_helper = bhs | ||||
|         self._db = db | ||||
|         self._bot = bot | ||||
|         self._users = users | ||||
|         self._clients = clients | ||||
|         self._servers = servers | ||||
|  | ||||
|     def _append_received_message_count(self, g_id: int): | ||||
|         try: | ||||
|             self._clients.append_received_message_count(self._bot.user.id, g_id, 1) | ||||
|             self._db.save_changes() | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f'Cannot edit client {self._bot.user.id}@{g_id}', e) | ||||
|  | ||||
|     def _handle_message_for_xp(self, message: discord.Message): | ||||
|         dc_user_id = message.author.id | ||||
|         try: | ||||
|             server = self._servers.get_server_by_discord_id(message.guild.id) | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f'Cannot get server {message.guild.id}', e) | ||||
|             return | ||||
|  | ||||
|         user: Optional[User] = None | ||||
|         try: | ||||
|             user = self._users.get_user_by_discord_id_and_server_id(dc_user_id, server.server_id) | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f'Cannot get user {dc_user_id}', e) | ||||
|             return | ||||
|  | ||||
|         if user is None: | ||||
|             self._logger.error(__name__, f'User not found {dc_user_id}') | ||||
|             return | ||||
|  | ||||
|         settings: BaseServerSettings = self._base_helper.get_config(message.guild.id) | ||||
|         old_xp = user.xp | ||||
|         user.xp += settings.xp_per_message | ||||
|         self._users.update_user(user) | ||||
|         self._db.save_changes() | ||||
|  | ||||
|         self._logger.debug(__name__, f'User {user} sent message. xp: from {old_xp} to {user.xp}') | ||||
|  | ||||
|     async def on_message(self, message: discord.Message): | ||||
|         self._logger.debug(__name__, f'Module {type(self)} started') | ||||
|         if message is None or message.guild is None: | ||||
|             return | ||||
|         self._append_received_message_count(message.guild.id) | ||||
|  | ||||
|         if not message.author.bot: | ||||
|             self._handle_message_for_xp(message) | ||||
							
								
								
									
										118
									
								
								src/modules/base/events/base_on_voice_state_update_event.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								src/modules/base/events/base_on_voice_state_update_event.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | ||||
| from datetime import datetime | ||||
| 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_discord.events import OnVoiceStateUpdateABC | ||||
|  | ||||
| from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC | ||||
| 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_joined_voice_channel_abc import UserJoinedVoiceChannelRepositoryABC | ||||
| from bot_data.abc.user_repository_abc import UserRepositoryABC | ||||
| from bot_data.model.server import Server | ||||
| 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): | ||||
|  | ||||
|     def __init__( | ||||
|             self, | ||||
|             config: ConfigurationABC, | ||||
|             logger: LoggerABC, | ||||
|             base_helper: BaseHelperABC, | ||||
|             servers: ServerRepositoryABC, | ||||
|             known_users: KnownUserRepositoryABC, | ||||
|             users: UserRepositoryABC, | ||||
|             user_joins: UserJoinedServerRepositoryABC, | ||||
|             user_joins_vc: UserJoinedVoiceChannelRepositoryABC, | ||||
|             db: DatabaseContextABC, | ||||
|     ): | ||||
|         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 | ||||
|         self._user_joins = user_joins | ||||
|         self._user_joins_vc = user_joins_vc | ||||
|         self._db = db | ||||
|  | ||||
|         self._logger.info(__name__, f'Module {type(self)} loaded') | ||||
|  | ||||
|     def _update_voice_state(self, joined: bool, dc_user_id: int, dc_channel_id: int, server: Server): | ||||
|         user: Optional[User] = None | ||||
|         try: | ||||
|             user = self._users.get_user_by_discord_id_and_server_id(dc_user_id, server.server_id) | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f'Cannot get user {dc_user_id}', e) | ||||
|             return | ||||
|  | ||||
|         if user is None: | ||||
|             self._logger.error(__name__, f'User not found {dc_user_id}') | ||||
|             return | ||||
|  | ||||
|         try: | ||||
|             if joined: | ||||
|                 join = UserJoinedVoiceChannel(user, dc_channel_id, datetime.now()) | ||||
|                 self._user_joins_vc.add_user_joined_voice_channel(join) | ||||
|                 self._db.save_changes() | ||||
|                 return | ||||
|  | ||||
|             settings: BaseServerSettings = self._get_config(server.discord_server_id) | ||||
|  | ||||
|             join = self._user_joins_vc.get_active_user_joined_voice_channel_by_user_id(user.user_id) | ||||
|             join.leaved_on = datetime.now() | ||||
|  | ||||
|             # ontime as hours | ||||
|             ontime = round((join.leaved_on - join.joined_on).total_seconds() / 3600, 2) | ||||
|             old_xp = user.xp | ||||
|             user.xp += round(ontime * settings.xp_per_ontime_hour) | ||||
|  | ||||
|             self._user_joins_vc.update_user_joined_voice_channel(join) | ||||
|             self._users.update_user(user) | ||||
|             self._db.save_changes() | ||||
|  | ||||
|             self._logger.debug(__name__, f'User {user} leaved_on {join.leaved_on}. Ontime: {ontime}h | xp: from {old_xp} to {user.xp}') | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f'Ontime validation failed', e) | ||||
|  | ||||
|     async def on_voice_state_update(self, member: discord.Member, before: discord.VoiceState, after: discord.VoiceState): | ||||
|         self._logger.debug(__name__, f'Module {type(self)} started') | ||||
|         self._logger.trace(__name__, f'Detected on_voice_state_update {member.id} from {before} to {after}') | ||||
|         settings: BaseServerSettings = self._base_helper.get_config(member.guild.id) | ||||
|         server = self._servers.get_server_by_discord_id(member.guild.id) | ||||
|  | ||||
|         try: | ||||
|             # join | ||||
|             if before.channel is None and after.channel is not None and after.channel.id not in settings.afk_channel_ids: | ||||
|                 self._logger.trace(__name__, f'User {member.id} joined {after.channel}') | ||||
|                 self._update_voice_state(True, member.id, after.channel.id, server) | ||||
|  | ||||
|             # leave | ||||
|             elif before.channel is not None and after.channel is None and before.channel.id not in settings.afk_channel_ids: | ||||
|                 self._logger.trace(__name__, f'User {member.id} left {before.channel}') | ||||
|                 self._update_voice_state(False, member.id, before.channel.id, server) | ||||
|  | ||||
|             # channel to channel | ||||
|             elif before.channel is not None and after.channel is not None: | ||||
|                 # joined | ||||
|                 if before.channel.id in settings.afk_channel_ids and after.channel.id not in settings.afk_channel_ids: | ||||
|                     self._logger.trace(__name__, f'User {member.id} joined {after.channel}') | ||||
|                     self._update_voice_state(True, member.id, after.channel.id, server) | ||||
|  | ||||
|                 # left | ||||
|                 elif after.channel.id in settings.afk_channel_ids and before.channel.id not in settings.afk_channel_ids: | ||||
|                     self._logger.trace(__name__, f'User {member.id} left {before.channel}') | ||||
|                     self._update_voice_state(False, member.id, before.channel.id, server) | ||||
|  | ||||
|                 else: | ||||
|                     self._logger.trace(__name__, f'User {member.id} switched to {after.channel}') | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f'Cannot handle voice state for user {member.id}', e) | ||||
							
								
								
									
										1
									
								
								src/modules/base/service/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/base/service/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| # imports | ||||
							
								
								
									
										14
									
								
								src/modules/base/service/base_helper_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/modules/base/service/base_helper_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| 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}') | ||||
							
								
								
									
										1
									
								
								src/modules/boot_log/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/boot_log/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| # imports:  | ||||
							
								
								
									
										46
									
								
								src/modules/boot_log/boot-log.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/modules/boot_log/boot-log.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| { | ||||
|   "ProjectSettings": { | ||||
|     "Name": "boot-log", | ||||
|     "Version": { | ||||
|       "Major": "0", | ||||
|       "Minor": "0", | ||||
|       "Micro": "0" | ||||
|     }, | ||||
|     "Author": "", | ||||
|     "AuthorEmail": "", | ||||
|     "Description": "", | ||||
|     "LongDescription": "", | ||||
|     "URL": "", | ||||
|     "CopyrightDate": "", | ||||
|     "CopyrightName": "", | ||||
|     "LicenseName": "", | ||||
|     "LicenseDescription": "", | ||||
|     "Dependencies": [ | ||||
|       "cpl-core>=2022.7.0.post2" | ||||
|     ], | ||||
|     "DevDependencies": [ | ||||
|       "cpl-cli>=2022.7.0.post2" | ||||
|     ], | ||||
|     "PythonVersion": ">=3.10.4", | ||||
|     "PythonPath": { | ||||
|       "linux": "" | ||||
|     }, | ||||
|     "Classifiers": [] | ||||
|   }, | ||||
|   "BuildSettings": { | ||||
|     "ProjectType": "library", | ||||
|     "SourcePath": "", | ||||
|     "OutputPath": "../../dist", | ||||
|     "Main": "boot_log.main", | ||||
|     "EntryPoint": "boot-log", | ||||
|     "IncludePackageData": false, | ||||
|     "Included": [], | ||||
|     "Excluded": [ | ||||
|       "*/__pycache__", | ||||
|       "*/logs", | ||||
|       "*/tests" | ||||
|     ], | ||||
|     "PackageData": {}, | ||||
|     "ProjectReferences": [] | ||||
|   } | ||||
| } | ||||
							
								
								
									
										17
									
								
								src/modules/boot_log/boot_log_extension.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/modules/boot_log/boot_log_extension.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| from datetime import datetime | ||||
|  | ||||
| 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 | ||||
|  | ||||
|  | ||||
| class BootLogExtension(ApplicationExtensionABC): | ||||
|  | ||||
|     def __init__(self): | ||||
|         pass | ||||
|  | ||||
|     async def run(self, config: ConfigurationABC, services: ServiceProviderABC): | ||||
|         logger: LoggerABC = services.get_service(LoggerABC) | ||||
|         logger.debug(__name__, 'BootLog extension started') | ||||
|         config.add_configuration('Bot_StartTime', str(datetime.now())) | ||||
							
								
								
									
										77
									
								
								src/modules/boot_log/boot_log_on_ready_event.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/modules/boot_log/boot_log_on_ready_event.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| from datetime import datetime | ||||
|  | ||||
| from cpl_core.configuration import ConfigurationABC | ||||
| from cpl_core.logging import LoggerABC | ||||
| from cpl_discord.events import OnReadyABC | ||||
| from cpl_discord.service import DiscordBotServiceABC | ||||
| 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 | ||||
|  | ||||
|  | ||||
| class BootLogOnReadyEvent(OnReadyABC): | ||||
|  | ||||
|     def __init__( | ||||
|             self, | ||||
|             config: ConfigurationABC, | ||||
|             logger: LoggerABC, | ||||
|             bot: DiscordBotServiceABC, | ||||
|             message_service: MessageServiceABC, | ||||
|             translate: TranslatePipe | ||||
|     ): | ||||
|         OnReadyABC.__init__(self) | ||||
|         self._config = config | ||||
|  | ||||
|         self._logger = logger | ||||
|         self._bot = bot | ||||
|         self._message_service = message_service | ||||
|         self._t = translate | ||||
|  | ||||
|         self._logger.info(__name__, f'Module {type(self)} loaded') | ||||
|  | ||||
|     async def on_ready(self): | ||||
|         self._logger.debug(__name__, f'Module {type(self)} started') | ||||
|         try: | ||||
|             start_time = self._config.get_configuration('Bot_StartTime') | ||||
|             init_time = round((datetime.now() - datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S.%f')).total_seconds(), 2) | ||||
|             self._config.add_configuration('InitTime', str(init_time)) | ||||
|             self._logger.debug(__name__, f'Bot Init time:  {init_time}s') | ||||
|             # print warning if initialisation took too long | ||||
|             if init_time >= 30: | ||||
|                 self._logger.warn( | ||||
|                     __name__, 'It takes long time to start the bot!') | ||||
|  | ||||
|             # print error if initialisation took way too long | ||||
|             elif init_time >= 90: | ||||
|                 self._logger.error( | ||||
|                     __name__, 'It takes very long time to start the bot!!!') | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, 'Init time calculation failed', e) | ||||
|             return | ||||
|  | ||||
|         for g in self._bot.guilds: | ||||
|             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!') | ||||
|                 return | ||||
|  | ||||
|             await self._message_service.send_channel_message( | ||||
|                 self._bot.get_channel( | ||||
|                     module_settings.login_message_channel_id | ||||
|                 ), | ||||
|                 self._t.transform('modules.boot_log.login_message').format(init_time) | ||||
|             ) | ||||
|             self._logger.info(__name__, 'Bot is ready') | ||||
|  | ||||
|         self._logger.trace(__name__, f'Module {type(self)} stopped') | ||||
							
								
								
									
										0
									
								
								src/modules/boot_log/configuration/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/modules/boot_log/configuration/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| import traceback | ||||
|  | ||||
| from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC | ||||
| from cpl_core.console import Console | ||||
|  | ||||
|  | ||||
| class BootLogServerSettings(ConfigurationModelABC): | ||||
|  | ||||
|     def __init__(self): | ||||
|         ConfigurationModelABC.__init__(self) | ||||
|  | ||||
|         self._id: int = 0 | ||||
|         self._login_message_channel_id: int = 0 | ||||
|  | ||||
|     @property | ||||
|     def id(self) -> int: | ||||
|         return self._id | ||||
|      | ||||
|     @property | ||||
|     def login_message_channel_id(self) -> int: | ||||
|         return self._login_message_channel_id | ||||
|  | ||||
|     def from_dict(self, settings: dict): | ||||
|         try: | ||||
|             self._id = int(settings['Id']) | ||||
|             self._login_message_channel_id = int(settings['LoginMessageChannelId']) | ||||
|         except Exception as e: | ||||
|             Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings') | ||||
|             Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') | ||||
							
								
								
									
										32
									
								
								src/modules/boot_log/configuration/boot_log_settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/modules/boot_log/configuration/boot_log_settings.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| import traceback | ||||
|  | ||||
| from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC | ||||
| from cpl_core.console import Console | ||||
| from cpl_query.extension import List | ||||
|  | ||||
| from modules.boot_log.configuration.boot_log_server_settings import BootLogServerSettings | ||||
|  | ||||
|  | ||||
| class BootLogSettings(ConfigurationModelABC): | ||||
|  | ||||
|     def __init__(self): | ||||
|         ConfigurationModelABC.__init__(self) | ||||
|  | ||||
|         self._servers: List[BootLogServerSettings] = List() | ||||
|  | ||||
|     @property | ||||
|     def servers(self) -> List[BootLogServerSettings]: | ||||
|         return self._servers | ||||
|  | ||||
|     def from_dict(self, settings: dict): | ||||
|         try: | ||||
|             servers = List(BootLogServerSettings) | ||||
|             for s in settings: | ||||
|                 st = BootLogServerSettings() | ||||
|                 settings[s]['Id'] = s | ||||
|                 st.from_dict(settings[s]) | ||||
|                 servers.append(st) | ||||
|             self._servers = servers | ||||
|         except Exception as e: | ||||
|             Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings') | ||||
|             Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') | ||||
							
								
								
									
										1
									
								
								src/modules/database/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/database/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| # imports:  | ||||
							
								
								
									
										46
									
								
								src/modules/database/database.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/modules/database/database.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| { | ||||
|   "ProjectSettings": { | ||||
|     "Name": "database", | ||||
|     "Version": { | ||||
|       "Major": "1", | ||||
|       "Minor": "0", | ||||
|       "Micro": "0.dev1" | ||||
|     }, | ||||
|     "Author": "Sven Heidemann", | ||||
|     "AuthorEmail": "sven.heidemann@sh-edraft.de", | ||||
|     "Description": "Keksdose bot - db module", | ||||
|     "LongDescription": "Discord bot  for the Keksdose discord Server - database module", | ||||
|     "URL": "https://www.sh-edraft.de", | ||||
|     "CopyrightDate": "2022", | ||||
|     "CopyrightName": "sh-edraft.de", | ||||
|     "LicenseName": "MIT", | ||||
|     "LicenseDescription": "MIT, see LICENSE for more details.", | ||||
|     "Dependencies": [ | ||||
|       "cpl-core>=2022.7.0.post2" | ||||
|     ], | ||||
|     "DevDependencies": [ | ||||
|       "cpl-cli>=2022.7.0.post2" | ||||
|     ], | ||||
|     "PythonVersion": ">=3.10.4", | ||||
|     "PythonPath": { | ||||
|       "linux": "" | ||||
|     }, | ||||
|     "Classifiers": [] | ||||
|   }, | ||||
|   "BuildSettings": { | ||||
|     "ProjectType": "library", | ||||
|     "SourcePath": "", | ||||
|     "OutputPath": "../../dist", | ||||
|     "Main": "database.main", | ||||
|     "EntryPoint": "database", | ||||
|     "IncludePackageData": false, | ||||
|     "Included": [], | ||||
|     "Excluded": [ | ||||
|       "*/__pycache__", | ||||
|       "*/logs", | ||||
|       "*/tests" | ||||
|     ], | ||||
|     "PackageData": {}, | ||||
|     "ProjectReferences": [] | ||||
|   } | ||||
| } | ||||
							
								
								
									
										21
									
								
								src/modules/database/database_extension.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/modules/database/database_extension.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| from datetime import datetime | ||||
|  | ||||
| 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_data.service.migration_service import MigrationService | ||||
|  | ||||
|  | ||||
| class DatabaseExtension(ApplicationExtensionABC): | ||||
|  | ||||
|     def __init__(self): | ||||
|         pass | ||||
|  | ||||
|     async def run(self, config: ConfigurationABC, services: ServiceProviderABC): | ||||
|         logger: LoggerABC = services.get_service(LoggerABC) | ||||
|         logger.debug(__name__, 'Database extension started') | ||||
|         config.add_configuration('Database_StartTime', str(datetime.now())) | ||||
|         migrations: MigrationService = services.get_service(MigrationService) | ||||
|         migrations.migrate() | ||||
							
								
								
									
										310
									
								
								src/modules/database/database_on_ready_event.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										310
									
								
								src/modules/database/database_on_ready_event.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,310 @@ | ||||
| from ctypes import Union | ||||
| from datetime import datetime, timedelta | ||||
|  | ||||
| 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 OnReadyABC | ||||
| from cpl_discord.service import DiscordBotServiceABC | ||||
|  | ||||
| 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_server_repository_abc import UserJoinedServerRepositoryABC | ||||
| from bot_data.abc.user_joined_voice_channel_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.user_repository_service import ServerRepositoryABC | ||||
|  | ||||
|  | ||||
| class DatabaseOnReadyEvent(OnReadyABC): | ||||
|  | ||||
|     def __init__( | ||||
|         self, | ||||
|         config: ConfigurationABC, | ||||
|         logger: LoggerABC, | ||||
|         bot: DiscordBotServiceABC, | ||||
|         db_context: DatabaseContextABC, | ||||
|         server_repo: ServerRepositoryABC, | ||||
|         user_repo: UserRepositoryABC, | ||||
|         client_repo: ClientRepositoryABC, | ||||
|         known_users: KnownUserRepositoryABC, | ||||
|         user_joins: UserJoinedServerRepositoryABC, | ||||
|         user_joins_vc: UserJoinedVoiceChannelRepositoryABC | ||||
|     ): | ||||
|         self._config = config | ||||
|  | ||||
|         self._logger = logger | ||||
|         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 | ||||
|  | ||||
|         OnReadyABC.__init__(self) | ||||
|         self._logger.info(__name__, f'Module {type(self)} loaded') | ||||
|  | ||||
|     def _validate_init_time(self): | ||||
|         try: | ||||
|             start_time = self._config.get_configuration('Database_StartTime') | ||||
|             init_time = round((datetime.now() - datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S.%f')).total_seconds(), 2) | ||||
|             self._config.add_configuration('Database_InitTime', str(init_time)) | ||||
|             self._logger.debug(__name__, f'Database Init time:  {init_time}s') | ||||
|             # print warning if initialisation took too long | ||||
|             if init_time >= 30: | ||||
|                 self._logger.warn( | ||||
|                     __name__, 'It takes long time to start the bot!') | ||||
|  | ||||
|             # print error if initialisation took way too long | ||||
|             elif init_time >= 90: | ||||
|                 self._logger.error( | ||||
|                     __name__, 'It takes very long time to start the bot!!!') | ||||
|         except Exception as e:  # | ||||
|             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.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.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.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.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.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, 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_server_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 | ||||
|  | ||||
|             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.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.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() | ||||
|                         settings: BaseSettings = 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_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: | ||||
|                         continue | ||||
|  | ||||
|                     user = self._users.find_user_by_discord_id_and_server_id(member.id, server.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) | ||||
|  | ||||
|     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._validate_init_time() | ||||
|         self._logger.trace(__name__, f'Module {type(self)} stopped') | ||||
							
								
								
									
										1
									
								
								src/modules/permission/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/permission/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| # imports:  | ||||
							
								
								
									
										25
									
								
								src/modules/permission/abc/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/modules/permission/abc/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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__ = 'modules.permission.abc' | ||||
| __author__ = 'Sven Heidemann' | ||||
| __license__ = 'MIT' | ||||
| __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' | ||||
| __version__ = '0.4.2' | ||||
|  | ||||
| from collections import namedtuple | ||||
|  | ||||
| # imports | ||||
|  | ||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||
| version_info = VersionInfo(major='0', minor='4', micro='2') | ||||
							
								
								
									
										39
									
								
								src/modules/permission/abc/permission_service_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/modules/permission/abc/permission_service_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| from abc import ABC, abstractmethod | ||||
|  | ||||
| import discord | ||||
|  | ||||
|  | ||||
| class PermissionServiceABC(ABC): | ||||
|  | ||||
|     @abstractmethod | ||||
|     def __init__(self): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def on_ready(self): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def on_member_update(self, before: discord.Member, after: discord.Member): pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_admin_role_ids(self, g_id: int) -> list[int]: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_admin_roles(self, g_id: int) -> list[discord.Role]: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_admins(self, g_id: int) -> list[discord.Member]: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_moderator_role_ids(self, g_id: int) -> list[int]: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_moderator_roles(self, g_id: int) -> list[discord.Role]: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_moderators(self, g_id: int) -> list[discord.Member]: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def is_member_admin(self, member: discord.Member) -> bool: pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def is_member_moderator(self, member: discord.Member) -> bool: pass | ||||
							
								
								
									
										25
									
								
								src/modules/permission/configuration/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/modules/permission/configuration/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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__ = 'modules.permission.configuration' | ||||
| __author__ = 'Sven Heidemann' | ||||
| __license__ = 'MIT' | ||||
| __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' | ||||
| __version__ = '0.4.2' | ||||
|  | ||||
| from collections import namedtuple | ||||
|  | ||||
| # imports | ||||
|  | ||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||
| version_info = VersionInfo(major='0', minor='4', micro='2') | ||||
| @@ -0,0 +1,38 @@ | ||||
| import traceback | ||||
|  | ||||
| from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC | ||||
| from cpl_core.console import Console | ||||
|  | ||||
|  | ||||
| class PermissionServerSettings(ConfigurationModelABC): | ||||
|  | ||||
|     def __init__(self): | ||||
|         ConfigurationModelABC.__init__(self) | ||||
|  | ||||
|         self._id: int = 0 | ||||
|         self._admin_roles: list[int] = [] | ||||
|         self._moderator_roles: list[int] = [] | ||||
|  | ||||
|     @property | ||||
|     def id(self) -> int: | ||||
|         return self._id | ||||
|  | ||||
|     @property | ||||
|     def admin_roles(self) -> list[int]: | ||||
|         return self._admin_roles | ||||
|  | ||||
|     @property | ||||
|     def moderator_roles(self) -> list[int]: | ||||
|         return self._moderator_roles | ||||
|  | ||||
|     def from_dict(self, settings: dict): | ||||
|         try: | ||||
|             self._id = int(settings['Id']) | ||||
|             for index in settings['AdminRoleIds']: | ||||
|                 self._admin_roles.append(int(index)) | ||||
|              | ||||
|             for index in settings['ModeratorRoleIds']: | ||||
|                 self._moderator_roles.append(int(index)) | ||||
|         except Exception as e: | ||||
|             Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {self.__name__} settings') | ||||
|             Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') | ||||
							
								
								
									
										32
									
								
								src/modules/permission/configuration/permission_settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/modules/permission/configuration/permission_settings.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| import traceback | ||||
|  | ||||
| from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC | ||||
| from cpl_core.console import Console | ||||
| from cpl_query.extension import List | ||||
|  | ||||
| from modules.permission.configuration.permission_server_settings import PermissionServerSettings | ||||
|  | ||||
|  | ||||
| class PermissionSettings(ConfigurationModelABC): | ||||
|  | ||||
|     def __init__(self): | ||||
|         ConfigurationModelABC.__init__(self) | ||||
|  | ||||
|         self._servers: List[PermissionServerSettings] = List() | ||||
|  | ||||
|     @property | ||||
|     def servers(self) -> List[PermissionServerSettings]: | ||||
|         return self._servers | ||||
|  | ||||
|     def from_dict(self, settings: dict): | ||||
|         try: | ||||
|             servers = List(PermissionServerSettings) | ||||
|             for s in settings: | ||||
|                 st = PermissionServerSettings() | ||||
|                 settings[s]['Id'] = s | ||||
|                 st.from_dict(settings[s]) | ||||
|                 servers.append(st) | ||||
|             self._servers = servers | ||||
|         except Exception as e: | ||||
|             Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings') | ||||
|             Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') | ||||
							
								
								
									
										0
									
								
								src/modules/permission/events/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/modules/permission/events/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| import discord | ||||
| from cpl_core.logging import LoggerABC | ||||
| from cpl_discord.events import OnMemberUpdateABC | ||||
|  | ||||
| from modules.permission.abc.permission_service_abc import PermissionServiceABC | ||||
|  | ||||
|  | ||||
| class PermissionOnMemberUpdateEvent(OnMemberUpdateABC): | ||||
|  | ||||
|     def __init__(self, logger: LoggerABC, permission_service: PermissionServiceABC): | ||||
|         OnMemberUpdateABC.__init__(self) | ||||
|         self._logger = logger | ||||
|         self._permission_service = permission_service | ||||
|  | ||||
|     async def on_member_update(self, before: discord.Member, after: discord.Member): | ||||
|         self._logger.debug(__name__, f'Module {type(self)} started') | ||||
|  | ||||
|         if before.roles != after.roles: | ||||
|             self._permission_service.on_member_update(before, after) | ||||
							
								
								
									
										16
									
								
								src/modules/permission/events/permission_on_ready_event.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/modules/permission/events/permission_on_ready_event.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| from cpl_core.logging import LoggerABC | ||||
| from cpl_discord.events import OnReadyABC | ||||
|  | ||||
| from modules.permission.abc.permission_service_abc import PermissionServiceABC | ||||
|  | ||||
|  | ||||
| class PermissionOnReadyEvent(OnReadyABC): | ||||
|  | ||||
|     def __init__(self, logger: LoggerABC, permission_service: PermissionServiceABC): | ||||
|         OnReadyABC.__init__(self) | ||||
|         self._logger = logger | ||||
|         self._permission_service = permission_service | ||||
|  | ||||
|     async def on_ready(self): | ||||
|         self._logger.debug(__name__, f'Module {type(self)} started') | ||||
|         self._permission_service.on_ready() | ||||
							
								
								
									
										46
									
								
								src/modules/permission/permission.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/modules/permission/permission.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| { | ||||
|   "ProjectSettings": { | ||||
|     "Name": "permission", | ||||
|     "Version": { | ||||
|       "Major": "0", | ||||
|       "Minor": "0", | ||||
|       "Micro": "0" | ||||
|     }, | ||||
|     "Author": "", | ||||
|     "AuthorEmail": "", | ||||
|     "Description": "", | ||||
|     "LongDescription": "", | ||||
|     "URL": "", | ||||
|     "CopyrightDate": "", | ||||
|     "CopyrightName": "", | ||||
|     "LicenseName": "", | ||||
|     "LicenseDescription": "", | ||||
|     "Dependencies": [ | ||||
|       "cpl-core>=2022.7.0.post2" | ||||
|     ], | ||||
|     "DevDependencies": [ | ||||
|       "cpl-cli>=2022.7.0.post2" | ||||
|     ], | ||||
|     "PythonVersion": ">=3.10.4", | ||||
|     "PythonPath": { | ||||
|       "linux": "" | ||||
|     }, | ||||
|     "Classifiers": [] | ||||
|   }, | ||||
|   "BuildSettings": { | ||||
|     "ProjectType": "library", | ||||
|     "SourcePath": "", | ||||
|     "OutputPath": "../../dist", | ||||
|     "Main": "permission.main", | ||||
|     "EntryPoint": "permission", | ||||
|     "IncludePackageData": false, | ||||
|     "Included": [], | ||||
|     "Excluded": [ | ||||
|       "*/__pycache__", | ||||
|       "*/logs", | ||||
|       "*/tests" | ||||
|     ], | ||||
|     "PackageData": {}, | ||||
|     "ProjectReferences": [] | ||||
|   } | ||||
| } | ||||
							
								
								
									
										25
									
								
								src/modules/permission/service/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/modules/permission/service/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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__ = 'modules.permission.service' | ||||
| __author__ = 'Sven Heidemann' | ||||
| __license__ = 'MIT' | ||||
| __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' | ||||
| __version__ = '0.4.2' | ||||
|  | ||||
| from collections import namedtuple | ||||
|  | ||||
| # imports | ||||
|  | ||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||
| version_info = VersionInfo(major='0', minor='4', micro='2') | ||||
							
								
								
									
										126
									
								
								src/modules/permission/service/permission_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								src/modules/permission/service/permission_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,126 @@ | ||||
| import discord | ||||
| from cpl_core.logging import LoggerABC | ||||
| from cpl_core.configuration import ConfigurationABC | ||||
| from cpl_discord.service import DiscordBotServiceABC | ||||
|  | ||||
| from modules.permission.abc.permission_service_abc import PermissionServiceABC | ||||
| from modules.permission.configuration.permission_server_settings import PermissionServerSettings | ||||
|  | ||||
|  | ||||
| class PermissionService(PermissionServiceABC): | ||||
|  | ||||
|     def __init__(self, logger: LoggerABC, bot: DiscordBotServiceABC, config: ConfigurationABC): | ||||
|         PermissionServiceABC.__init__(self) | ||||
|         self._logger = logger | ||||
|         self._bot = bot | ||||
|         self._config = config | ||||
|  | ||||
|         self._admin_role_ids: dict[int, list[int]] = {} | ||||
|         self._admin_roles: dict[int, list[discord.Role]] = {} | ||||
|         self._admins: dict[int, list[discord.Member]] = {} | ||||
|  | ||||
|         self._moderator_role_ids: dict[int, list[int]] = {} | ||||
|         self._moderator_roles: dict[int, list[discord.Role]] = {} | ||||
|         self._moderators: dict[int, list[discord.Member]] = {} | ||||
|  | ||||
|     def on_ready(self): | ||||
|         for guild in self._bot.guilds: | ||||
|             guild: discord.Guild = guild | ||||
|             self._logger.debug(__name__, f'Validate permission settings') | ||||
|  | ||||
|             settings: PermissionServerSettings = self._config.get_configuration(f'PermissionServerSettings_{guild.id}') | ||||
|             if settings is None: | ||||
|                 self._logger.error(__name__, 'Permission settings not found') | ||||
|                 return | ||||
|  | ||||
|             self._admin_role_ids[guild.id] = settings.admin_roles | ||||
|             self._moderator_role_ids[guild.id] = settings.moderator_roles | ||||
|  | ||||
|             admin_roles = [] | ||||
|             admins = [] | ||||
|  | ||||
|             mod_roles = [] | ||||
|             mods = [] | ||||
|  | ||||
|             for role in guild.roles: | ||||
|                 role: discord.Role = role | ||||
|  | ||||
|                 if role.id in self._admin_role_ids[guild.id]: | ||||
|                     admin_roles.append(role) | ||||
|                     self._logger.trace(__name__, f'Added admin role {role}') | ||||
|  | ||||
|                     for member in role.members: | ||||
|                         admins.append(member) | ||||
|                         self._logger.trace(__name__, f'Added admin {member}') | ||||
|  | ||||
|                 if role.id in self._moderator_role_ids[guild.id]: | ||||
|                     mod_roles.append(role) | ||||
|                     self._logger.trace(__name__, f'Added moderator role {role}') | ||||
|  | ||||
|                     for member in role.members: | ||||
|                         mods.append(member) | ||||
|                         self._logger.trace(__name__, f'Added moderator {member}') | ||||
|  | ||||
|             self._admin_roles[guild.id] = admin_roles | ||||
|             self._admins[guild.id] = admins | ||||
|             self._moderator_roles[guild.id] = mod_roles | ||||
|             self._moderators[guild.id] = mods | ||||
|  | ||||
|         self._logger.error(__name__, f'USERS {self._admins} {self._moderators}') | ||||
|  | ||||
|     def on_member_update(self, before: discord.Member, after: discord.Member): | ||||
|         g_id = after.guild.id | ||||
|  | ||||
|         for admin_role in self._admin_roles[g_id]: | ||||
|             if admin_role in before.roles and admin_role not in after.roles: | ||||
|                 self._admins[g_id].remove(after) | ||||
|                 self._logger.trace(__name__, f'Removed {after.id} from admins') | ||||
|  | ||||
|             elif admin_role in after.roles and admin_role not in before.roles: | ||||
|                 self._admins[g_id].append(after) | ||||
|                 self._logger.trace(__name__, f'Added {after.id} to admins') | ||||
|  | ||||
|         for moderator_role in self._moderator_roles[g_id]: | ||||
|             if moderator_role in before.roles and moderator_role not in after.roles: | ||||
|                 self._moderators[g_id].remove(after) | ||||
|                 self._logger.trace(__name__, f'Removed {after.id} from moderators') | ||||
|  | ||||
|             elif moderator_role in after.roles and moderator_role not in before.roles: | ||||
|                 self._moderators[g_id].append(after) | ||||
|                 self._logger.trace(__name__, f'Added {after.id} to moderators') | ||||
|  | ||||
|     def get_admin_role_ids(self, g_id: int) -> list[int]: | ||||
|         return self._admin_role_ids[g_id] | ||||
|  | ||||
|     def get_admin_roles(self, g_id: int) -> list[discord.Role]: | ||||
|         return self._admin_roles[g_id] | ||||
|  | ||||
|     def get_admins(self, g_id: int) -> list[discord.Member]: | ||||
|         return self._admins[g_id] | ||||
|  | ||||
|     def get_moderator_role_ids(self, g_id: int) -> list[int]: | ||||
|         return self._moderator_role_ids[g_id] | ||||
|  | ||||
|     def get_moderator_roles(self, g_id: int) -> list[discord.Role]: | ||||
|         return self._moderator_roles[g_id] | ||||
|  | ||||
|     def get_moderators(self, g_id: int) -> list[discord.Member]: | ||||
|         return self._moderators[g_id] | ||||
|  | ||||
|     def is_member_admin(self, member: discord.Member) -> bool: | ||||
|         role_match = False | ||||
|  | ||||
|         for role in member.roles: | ||||
|             if role in self._admin_roles: | ||||
|                 role_match = True | ||||
|  | ||||
|         return member in self._admins[member.guild.id] or role_match | ||||
|  | ||||
|     def is_member_moderator(self, member: discord.Member) -> bool: | ||||
|         role_match = False | ||||
|  | ||||
|         for role in member.roles: | ||||
|             if role in self._moderator_roles: | ||||
|                 role_match = True | ||||
|  | ||||
|         return member in self._moderators[member.guild.id] or role_match or self.is_member_admin(member) | ||||
		Reference in New Issue
	
	Block a user