[WIP] Added basic commands & functionality of Gismo@0.4.10
This commit is contained in:
		| @@ -4,8 +4,18 @@ | |||||||
|     "Projects": { |     "Projects": { | ||||||
|       "bot": "src/bot/bot.json", |       "bot": "src/bot/bot.json", | ||||||
|       "bot-core": "src/bot_core/bot-core.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:  | # 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.console import Console | ||||||
| from cpl_core.dependency_injection import ServiceProviderABC | from cpl_core.dependency_injection import ServiceProviderABC | ||||||
| from cpl_core.logging import LoggerABC | 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_discord.service import DiscordBotServiceABC, DiscordBotService | ||||||
| from cpl_translation import TranslatePipe, TranslationServiceABC, TranslationSettings | 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): | class Application(DiscordBotApplicationABC): | ||||||
|  |  | ||||||
| @@ -22,8 +33,21 @@ class Application(DiscordBotApplicationABC): | |||||||
|         self._translation: TranslationServiceABC = services.get_service(TranslationServiceABC) |         self._translation: TranslationServiceABC = services.get_service(TranslationServiceABC) | ||||||
|         self._translate: TranslatePipe = services.get_service(TranslatePipe) |         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): |     async def configure(self): | ||||||
|         self._translation.load_by_settings(self._configuration.get_configuration(TranslationSettings)) |         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): |     async def main(self): | ||||||
|         try: |         try: | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ | |||||||
|     "LicenseDescription": "MIT, see LICENSE for more details.", |     "LicenseDescription": "MIT, see LICENSE for more details.", | ||||||
|     "Dependencies": [ |     "Dependencies": [ | ||||||
|       "cpl-core>=2022.7.0.post1", |       "cpl-core>=2022.7.0.post1", | ||||||
|       "cpl-translation==2022.7.0.post1", |       "cpl-translation==2022.7.0.post2", | ||||||
|       "cpl-query==2022.7.0", |       "cpl-query==2022.7.0", | ||||||
|       "cpl-discord==2022.7.0.post1" |       "cpl-discord==2022.7.0.post1" | ||||||
|     ], |     ], | ||||||
|   | |||||||
| @@ -20,14 +20,5 @@ | |||||||
|   "DiscordBot": { |   "DiscordBot": { | ||||||
|     "Token": "OTA5ODc4NDcyNzExNzU3ODQ1.YZKsXA.8p-g1c37EBZzYYW09Fvr7egQzhE", |     "Token": "OTA5ODc4NDcyNzExNzU3ODQ1.YZKsXA.8p-g1c37EBZzYYW09Fvr7egQzhE", | ||||||
|     "Prefix": "!kd " |     "Prefix": "!kd " | ||||||
|   }, |  | ||||||
|   "Bot": { |  | ||||||
|     "Servers": [ |  | ||||||
|       { |  | ||||||
|         "Id": "910199451145076828", |  | ||||||
|         "MessageDeleteTimer": 2, |  | ||||||
|         "BotHasNoPermissionMessage": "Ich habe keine Berechtigungen :(" |  | ||||||
|       } |  | ||||||
|     ] |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -1,31 +1,58 @@ | |||||||
| { | { | ||||||
|     "LoggingSettings": { |   "LoggingSettings": { | ||||||
|         "Path": "logs/", |     "Path": "logs/", | ||||||
|         "Filename": "log_dev.log", |     "Filename": "log_dev.log", | ||||||
|         "ConsoleLogLevel": "TRACE", |     "ConsoleLogLevel": "TRACE", | ||||||
|         "FileLogLevel": "TRACE" |     "FileLogLevel": "TRACE" | ||||||
|  |   }, | ||||||
|  |   "DatabaseSettings": { | ||||||
|  |     "Host": "localhost", | ||||||
|  |     "User": "kd_kdb", | ||||||
|  |     "Password": "VGpZcihrb0N2T2MyZUlURQ==", | ||||||
|  |     "Database": "keksdose_bot_dev", | ||||||
|  |     "Charset": "utf8mb4", | ||||||
|  |     "UseUnicode": "true", | ||||||
|  |     "Buffered": "true", | ||||||
|  |     "AuthPlugin": "mysql_native_password" | ||||||
|  |   }, | ||||||
|  |   "DiscordBot": { | ||||||
|  |     "Token": "OTExNTc0NDQyMzMxNzM0MDI2.YZjX2w.k7N2qTkvkDD7j9bT4Nrdl4qBHlI", | ||||||
|  |     "Prefix": "!kde " | ||||||
|  |   }, | ||||||
|  |   "Bot": { | ||||||
|  |     "511824600884051979": { | ||||||
|  |       "MessageDeleteTimer": 2 | ||||||
|     }, |     }, | ||||||
|     "DatabaseSettings": { |     "910199451145076828": { | ||||||
|         "Host": "localhost", |       "MessageDeleteTimer": 2 | ||||||
|         "User": "sh_gismo", |  | ||||||
|         "Password": "c2hfZ2lzbW8=", |  | ||||||
|         "Database": "sh_gismo_dev", |  | ||||||
|         "Charset": "utf8mb4", |  | ||||||
|         "UseUnicode": "true", |  | ||||||
|         "Buffered": "true", |  | ||||||
|         "AuthPlugin": "mysql_native_password" |  | ||||||
|     }, |  | ||||||
|     "DiscordBot": { |  | ||||||
|         "Token": "OTExNTc0NDQyMzMxNzM0MDI2.YZjX2w.k7N2qTkvkDD7j9bT4Nrdl4qBHlI", |  | ||||||
|         "Prefix": "!kde " |  | ||||||
|     }, |  | ||||||
|     "Bot": { |  | ||||||
|         "Servers": [ |  | ||||||
|             { |  | ||||||
|                 "Id": "910199451145076828", |  | ||||||
|                 "MessageDeleteTimer": 2, |  | ||||||
|                 "BotHasNoPermissionMessage": "Ich habe keine Berechtigungen :(" |  | ||||||
|             } |  | ||||||
|         ] |  | ||||||
|     } |     } | ||||||
| } |   }, | ||||||
|  |   "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": { |   "Discord": { | ||||||
|     "Token": "OTEwMjAxNjA1NDkwNjEwMjA3.YZPZTQ.lUj2Bs5pQAv4AJ_tb_mHMTpIRls" |     "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.application import Application | ||||||
| from bot.startup import Startup | 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: | class Main: | ||||||
| @@ -14,6 +18,10 @@ class Main: | |||||||
|  |  | ||||||
|     async def main(self): |     async def main(self): | ||||||
|         app_builder = ApplicationBuilder(Application) |         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) |         app_builder.use_startup(Startup) | ||||||
|         self._app: Application = await app_builder.build_async() |         self._app: Application = await app_builder.build_async() | ||||||
|         await self._app.run_async() |         await self._app.run_async() | ||||||
|   | |||||||
| @@ -4,9 +4,31 @@ from typing import Optional | |||||||
|  |  | ||||||
| from cpl_core.application import StartupABC | from cpl_core.application import StartupABC | ||||||
| from cpl_core.configuration import ConfigurationABC | from cpl_core.configuration import ConfigurationABC | ||||||
|  | from cpl_core.database import DatabaseSettings | ||||||
| from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC | from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC | ||||||
| from cpl_core.environment import ApplicationEnvironment | 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): | class Startup(StartupABC): | ||||||
| @@ -34,7 +56,23 @@ class Startup(StartupABC): | |||||||
|     def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: |     def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: | ||||||
|         services.add_logging() |         services.add_logging() | ||||||
|         services.add_translation() |         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() |         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": { |   "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:  | # 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