diff --git a/cpl-workspace.json b/cpl-workspace.json index 098991ab..663b790a 100644 --- a/cpl-workspace.json +++ b/cpl-workspace.json @@ -6,6 +6,7 @@ "bot-core": "src/bot_core/bot-core.json", "bot-data": "src/bot_data/bot-data.json", "admin": "src/modules/admin/admin.json", + "auto-role": "src/modules/admin/auto-role.json", "base": "src/modules/base/base.json", "boot-log": "src/modules/boot_log/boot-log.json", "database": "src/modules/database/database.json", diff --git a/src/bot/config/feature-flags.json b/src/bot/config/feature-flags.json index 5c347644..b20c9cca 100644 --- a/src/bot/config/feature-flags.json +++ b/src/bot/config/feature-flags.json @@ -1,6 +1,7 @@ { "FeatureFlags": { "AdminModule": true, + "AutoRoleModule": true, "BaseModule": true, "BootLogModule": true, "CoreModule": true, diff --git a/src/bot/module_list.py b/src/bot/module_list.py index f7690033..6e9670ff 100644 --- a/src/bot/module_list.py +++ b/src/bot/module_list.py @@ -4,6 +4,7 @@ from bot_core.core_extension.core_extension_module import CoreExtensionModule from bot_core.core_module import CoreModule from bot_data.data_module import DataModule from modules.admin.admin_module import AdminModule +from modules.autorole.auto_role_module import AutoRoleModule from modules.base.base_module import BaseModule from modules.boot_log.boot_log_module import BootLogModule from modules.database.database_module import DatabaseModule @@ -20,6 +21,7 @@ class ModuleList: CoreModule, # has to be first! DataModule, AdminModule, + AutoRoleModule, BaseModule, DatabaseModule, ModeratorModule, diff --git a/src/bot/startup_migration_extension.py b/src/bot/startup_migration_extension.py index a40a0516..b8f7ff0e 100644 --- a/src/bot/startup_migration_extension.py +++ b/src/bot/startup_migration_extension.py @@ -4,6 +4,7 @@ from cpl_core.dependency_injection import ServiceCollectionABC from cpl_core.environment import ApplicationEnvironmentABC from bot_data.abc.migration_abc import MigrationABC +from bot_data.migration.auto_role_migration import AutoRoleMigration from bot_data.migration.initial_migration import InitialMigration from bot_data.service.migration_service import MigrationService @@ -19,3 +20,4 @@ class StartupMigrationExtension(StartupExtensionABC): def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): services.add_transient(MigrationService) services.add_transient(MigrationABC, InitialMigration) + services.add_transient(MigrationABC, AutoRoleMigration) # 03.10.2022 #54 - 0.2.2 diff --git a/src/bot_core/configuration/feature_flags_enum.py b/src/bot_core/configuration/feature_flags_enum.py index 91e2ca91..dac193b1 100644 --- a/src/bot_core/configuration/feature_flags_enum.py +++ b/src/bot_core/configuration/feature_flags_enum.py @@ -5,6 +5,7 @@ class FeatureFlagsEnum(Enum): # modules admin_module = 'AdminModule' + auto_role_module = 'AutoRoleModule' base_module = 'BaseModule' boot_log_module = 'BootLogModule' core_module = 'CoreModule' diff --git a/src/bot_core/configuration/feature_flags_settings.py b/src/bot_core/configuration/feature_flags_settings.py index 8fb815f7..4556e784 100644 --- a/src/bot_core/configuration/feature_flags_settings.py +++ b/src/bot_core/configuration/feature_flags_settings.py @@ -15,6 +15,7 @@ class FeatureFlagsSettings(ConfigurationModelABC): self._flags = { # modules FeatureFlagsEnum.admin_module.value: False, # 02.10.2022 #48 + FeatureFlagsEnum.auto_role_module.value: True, # 03.10.2022 #54 FeatureFlagsEnum.base_module.value: True, # 02.10.2022 #48 FeatureFlagsEnum.boot_log_module.value: True, # 02.10.2022 #48 FeatureFlagsEnum.core_module.value: True, # 03.10.2022 #56 diff --git a/src/bot_data/migration/auto_role_migration.py b/src/bot_data/migration/auto_role_migration.py new file mode 100644 index 00000000..9aad5f72 --- /dev/null +++ b/src/bot_data/migration/auto_role_migration.py @@ -0,0 +1,45 @@ +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.migration_abc import MigrationABC +from bot_data.db_context import DBContext + + +class AutoRoleMigration(MigrationABC): + + def __init__(self, logger: DatabaseLogger, 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 `AutoRoles` ( + `AutoRoleId` BIGINT NOT NULL AUTO_INCREMENT, + `ServerId` BIGINT, + `DiscordMessageId` BIGINT NOT NULL, + `CreatedAt` DATETIME(6), + `LastModifiedAt` DATETIME(6), + PRIMARY KEY(`AutoRoleId`) + ); + """) + ) + + self._cursor.execute( + str(f""" + CREATE TABLE IF NOT EXISTS `AutoRoleRules` ( + `AutoRoleRuleId` BIGINT NOT NULL AUTO_INCREMENT, + `AutoRoleId` BIGINT, + `DiscordEmojiId` BIGINT NOT NULL, + `DiscordRoleId` BIGINT NOT NULL, + `CreatedAt` DATETIME(6), + `LastModifiedAt` DATETIME(6), + PRIMARY KEY(`AutoRoleRuleId`) + ); + """) + ) + + def downgrade(self): + self._cursor.execute('DROP TABLE `AutoRole`;') + self._cursor.execute('DROP TABLE `AutoRoleRules`;') diff --git a/src/bot_data/model/auto_role.py b/src/bot_data/model/auto_role.py new file mode 100644 index 00000000..9d02e514 --- /dev/null +++ b/src/bot_data/model/auto_role.py @@ -0,0 +1,66 @@ +from datetime import datetime +from typing import Optional + +from cpl_core.database import TableABC + + +class AutoRole(TableABC): + + def __init__(self, server_id: int, dc_message_id: int, created_at: datetime=None, modified_at: datetime=None, id=0): + self._auto_role_id = id + self._server_id = server_id + self._discord_message_id = dc_message_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 + + @staticmethod + def get_select_all_string() -> str: + return str(f""" + SELECT * FROM `AutoRoles`; + """) + + @staticmethod + def get_select_by_id_string(id: int) -> str: + return str(f""" + SELECT * FROM `AutoRoles` + WHERE `AutoRoleId` = {id}; + """) + + @staticmethod + def get_select_by_server_id_string(id: int) -> str: + return str(f""" + SELECT * FROM `AutoRoles` + WHERE `ServerId` = {id}; + """) + + @property + def insert_string(self) -> str: + return str(f""" + INSERT INTO `AutoRoles` ( + `ServerId`, `DiscordMessageId`, `CreatedAt`, `LastModifiedAt` + ) VALUES ( + {self._server_id}, + {self._discord_message_id}, + '{self._created_at}', + '{self._modified_at}' + ); + """) + + @property + def udpate_string(self) -> str: + return str(f""" + UPDATE `AutoRoles` + SET `ServerId` = {self._server_id}, + SET `DiscordMessageId` = {self._discord_message_id}, + `LastModifiedAt` = '{self._modified_at}' + WHERE `AutoRoleId` = {self._auto_role_id}; + """) + + @property + def delete_string(self) -> str: + return str(f""" + DELETE FROM `AutoRoles` + WHERE `AutoRoleId` = {self._auto_role_id}; + """) diff --git a/src/bot_data/model/auto_role_rule.py b/src/bot_data/model/auto_role_rule.py new file mode 100644 index 00000000..f123615a --- /dev/null +++ b/src/bot_data/model/auto_role_rule.py @@ -0,0 +1,69 @@ +from datetime import datetime +from typing import Optional + +from cpl_core.database import TableABC + + +class AutoRoleRule(TableABC): + + def __init__(self, auto_role_id: int, discord_emoji_id: int, discord_role_id: int, created_at: datetime=None, modified_at: datetime=None, id=0): + self._auto_role_rule_id = id + self._auto_role_id = auto_role_id + self._discord_emoji_id = discord_emoji_id + self._discord_role_id = discord_role_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 + + @staticmethod + def get_select_all_string() -> str: + return str(f""" + SELECT * FROM `AutoRoleRules`; + """) + + @staticmethod + def get_select_by_id_string(id: int) -> str: + return str(f""" + SELECT * FROM `AutoRoleRules` + WHERE `AutoRoleRuleId` = {id}; + """) + + @staticmethod + def get_select_by_server_id_string(id: int) -> str: + return str(f""" + SELECT * FROM `AutoRoleRules` + WHERE `ServerId` = {id}; + """) + + @property + def insert_string(self) -> str: + return str(f""" + INSERT INTO `AutoRoleRules` ( + `AutoRoleId`, `DiscordEmojiId`, `DiscordRoleId`, `CreatedAt`, `LastModifiedAt` + ) VALUES ( + {self._auto_role_id}, + {self._discord_emoji_id}, + {self._discord_role_id}, + '{self._created_at}', + '{self._modified_at}' + ); + """) + + @property + def udpate_string(self) -> str: + return str(f""" + UPDATE `AutoRoleRules` + SET `AutoRoleId` = {self._auto_role_id}, + SET `DiscordEmojiId` = {self._discord_emoji_id}, + SET `DiscordRoleId` = {self._discord_role_id}, + `LastModifiedAt` = '{self._modified_at}' + WHERE `AutoRoleRuleId` = {self._auto_role_id}; + """) + + @property + def delete_string(self) -> str: + return str(f""" + DELETE FROM `AutoRoleRules` + WHERE `AutoRoleRuleId` = {self._auto_role_id}; + """) diff --git a/src/bot_data/model/server.py b/src/bot_data/model/server.py index 14cddefd..c3054952 100644 --- a/src/bot_data/model/server.py +++ b/src/bot_data/model/server.py @@ -60,12 +60,12 @@ class Server(TableABC): UPDATE `Servers` SET `DiscordServerId` = {self._discord_server_id}, `LastModifiedAt` = '{self._modified_at}' - WHERE `Id` = {self._server_id}; + WHERE `ServerId` = {self._server_id}; """) @property def delete_string(self) -> str: return str(f""" DELETE FROM `Servers` - WHERE `Id` = {self._server_id}; + WHERE `ServerId` = {self._server_id}; """) diff --git a/src/bot_data/service/auto_role_repository_service.py b/src/bot_data/service/auto_role_repository_service.py new file mode 100644 index 00000000..728d2bc6 --- /dev/null +++ b/src/bot_data/service/auto_role_repository_service.py @@ -0,0 +1,72 @@ +from typing import Optional + +from cpl_core.database.context import DatabaseContextABC +from cpl_query.extension import List + +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.model.server import Server + + +class ServerRepositoryService(ServerRepositoryABC): + + def __init__(self, logger: DatabaseLogger, 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) diff --git a/src/modules/autorole/__init__.py b/src/modules/autorole/__init__.py new file mode 100644 index 00000000..fc1dc7f9 --- /dev/null +++ b/src/modules/autorole/__init__.py @@ -0,0 +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__ = 'modules.admin' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2022 sh-edraft.de' +__version__ = '0.2.1' + +from collections import namedtuple + + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='2', micro='1') diff --git a/src/modules/autorole/auto-role.json b/src/modules/autorole/auto-role.json new file mode 100644 index 00000000..8e29094c --- /dev/null +++ b/src/modules/autorole/auto-role.json @@ -0,0 +1,46 @@ +{ + "ProjectSettings": { + "Name": "auto-role", + "Version": { + "Major": "0", + "Minor": "0", + "Micro": "0" + }, + "Author": "", + "AuthorEmail": "", + "Description": "", + "LongDescription": "", + "URL": "", + "CopyrightDate": "", + "CopyrightName": "", + "LicenseName": "", + "LicenseDescription": "", + "Dependencies": [ + "cpl-core>=2022.10.0.post5" + ], + "DevDependencies": [ + "cpl-cli>=2022.10.0" + ], + "PythonVersion": ">=3.10.4", + "PythonPath": { + "linux": "" + }, + "Classifiers": [] + }, + "BuildSettings": { + "ProjectType": "library", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "admin.main", + "EntryPoint": "admin", + "IncludePackageData": false, + "Included": [], + "Excluded": [ + "*/__pycache__", + "*/logs", + "*/tests" + ], + "PackageData": {}, + "ProjectReferences": [] + } +} \ No newline at end of file diff --git a/src/modules/autorole/auto_role_module.py b/src/modules/autorole/auto_role_module.py new file mode 100644 index 00000000..9afd273e --- /dev/null +++ b/src/modules/autorole/auto_role_module.py @@ -0,0 +1,21 @@ +from cpl_core.configuration import ConfigurationABC +from cpl_core.dependency_injection import ServiceCollectionABC +from cpl_core.environment import ApplicationEnvironmentABC +from cpl_discord.service.discord_collection_abc import DiscordCollectionABC + +from bot_core.abc.module_abc import ModuleABC +from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum + + +class AutoRoleModule(ModuleABC): + + def __init__(self, dc: DiscordCollectionABC): + ModuleABC.__init__(self, dc, FeatureFlagsEnum.auto_role_module) + + def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC): + pass + + def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): + # commands + # events + pass