diff --git a/kdb-bot/src/bot/translation/de.json b/kdb-bot/src/bot/translation/de.json index a377bcb4..889bf26a 100644 --- a/kdb-bot/src/bot/translation/de.json +++ b/kdb-bot/src/bot/translation/de.json @@ -147,6 +147,23 @@ "base": { "afk_command_channel_missing_message": "Zu unfähig einem Sprachkanal beizutreten?", "afk_command_move_message": "Ich verschiebe dich ja schon... (◔_◔)", + "game_server": { + "error": { + "nothing_found": "Keine Level Einträge gefunden." + }, + "list": { + "title": "Gameserver", + "description": "Konfigurierte Gameserver:", + "name": "Name", + "api_key": "API Key" + }, + "add": { + "success": "Gameserver {} wurde hinzugefügt :)" + }, + "remove": { + "success": "Gameserver wurde entfernt :D" + } + }, "goodbye_message": "Schade, dass du uns so schnell verlässt :(", "info": { "description": "Informationen über mich", diff --git a/kdb-bot/src/bot_data/abc/game_server_repository_abc.py b/kdb-bot/src/bot_data/abc/game_server_repository_abc.py new file mode 100644 index 00000000..50e6fe7a --- /dev/null +++ b/kdb-bot/src/bot_data/abc/game_server_repository_abc.py @@ -0,0 +1,39 @@ +from abc import ABC, abstractmethod + +from cpl_query.extension import List + +from bot_data.model.game_server import GameServer + + +class GameServerRepositoryABC(ABC): + @abstractmethod + def __init__(self): + pass + + @abstractmethod + def get_game_servers(self) -> List[GameServer]: + pass + + @abstractmethod + def get_game_server_by_id(self, id: int) -> GameServer: + pass + + @abstractmethod + def get_game_servers_by_server_id(self, id: int) -> List[GameServer]: + pass + + @abstractmethod + def get_game_server_by_api_key_id(self, id: int) -> GameServer: + pass + + @abstractmethod + def add_game_server(self, game_server: GameServer): + pass + + @abstractmethod + def update_game_server(self, game_server: GameServer): + pass + + @abstractmethod + def delete_game_server(self, game_server: GameServer): + pass diff --git a/kdb-bot/src/bot_data/abc/user_joined_game_server_repository_abc.py b/kdb-bot/src/bot_data/abc/user_joined_game_server_repository_abc.py index 97a0358b..266e90b5 100644 --- a/kdb-bot/src/bot_data/abc/user_joined_game_server_repository_abc.py +++ b/kdb-bot/src/bot_data/abc/user_joined_game_server_repository_abc.py @@ -11,6 +11,10 @@ class UserJoinedGameServerRepositoryABC(ABC): def __init__(self): pass + # @abstractmethod + # def get_game_server_by_api_key(self) -> List[UserJoinedGameServer]: + # pass + @abstractmethod def get_user_joined_game_servers(self) -> List[UserJoinedGameServer]: pass diff --git a/kdb-bot/src/bot_data/data_module.py b/kdb-bot/src/bot_data/data_module.py index f1bf1e41..d180e97e 100644 --- a/kdb-bot/src/bot_data/data_module.py +++ b/kdb-bot/src/bot_data/data_module.py @@ -9,6 +9,7 @@ from bot_data.abc.api_key_repository_abc import ApiKeyRepositoryABC from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC from bot_data.abc.client_repository_abc import ClientRepositoryABC +from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC from bot_data.abc.level_repository_abc import LevelRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC @@ -26,6 +27,7 @@ from bot_data.service.api_key_repository_service import ApiKeyRepositoryService from bot_data.service.auth_user_repository_service import AuthUserRepositoryService from bot_data.service.auto_role_repository_service import AutoRoleRepositoryService from bot_data.service.client_repository_service import ClientRepositoryService +from bot_data.service.game_server_repository_service import GameServerRepositoryService from bot_data.service.known_user_repository_service import KnownUserRepositoryService from bot_data.service.level_repository_service import LevelRepositoryService from bot_data.service.seeder_service import SeederService @@ -68,5 +70,6 @@ class DataModule(ModuleABC): UserMessageCountPerHourRepositoryABC, UserMessageCountPerHourRepositoryService, ) + services.add_transient(GameServerRepositoryABC, GameServerRepositoryService) services.add_transient(SeederService) diff --git a/kdb-bot/src/bot_data/model/game_server.py b/kdb-bot/src/bot_data/model/game_server.py index 0afc1ab3..ff886044 100644 --- a/kdb-bot/src/bot_data/model/game_server.py +++ b/kdb-bot/src/bot_data/model/game_server.py @@ -57,7 +57,7 @@ class GameServer(TableABC): def get_select_all_string() -> str: return str( f""" - SELECT * FROM `GameServer`; + SELECT * FROM `GameServers`; """ ) @@ -65,16 +65,34 @@ class GameServer(TableABC): def get_select_by_id_string(id: int) -> str: return str( f""" - SELECT * FROM `GameServer` + SELECT * FROM `GameServers` WHERE `Id` = {id}; """ ) + @staticmethod + def get_select_by_api_key_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `GameServers` + WHERE `ApiKeyId` = {id}; + """ + ) + + @staticmethod + def get_select_by_server_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `GameServers` + WHERE `ServerId` = {id}; + """ + ) + @staticmethod def get_select_by_user_id_string(id: int) -> str: return str( f""" - SELECT * FROM `GameServer` + SELECT * FROM `GameServers` WHERE `UserId` = {id}; """ ) @@ -83,8 +101,8 @@ class GameServer(TableABC): def insert_string(self) -> str: return str( f""" - INSERT INTO `GameServer` ( - `Name`, `ServerId`, `ApiKeyId`, CreatedAt`, `LastModifiedAt` + INSERT INTO `GameServers` ( + `Name`, `ServerId`, `ApiKeyId`, `CreatedAt`, `LastModifiedAt` ) VALUES ( '{self._name}', {self._server.id}, @@ -99,7 +117,7 @@ class GameServer(TableABC): def udpate_string(self) -> str: return str( f""" - UPDATE `GameServer` + UPDATE `GameServers` SET `LastModifiedAt` = '{self._modified_at}' WHERE `Id` = {self._id}; """ @@ -109,7 +127,7 @@ class GameServer(TableABC): def delete_string(self) -> str: return str( f""" - DELETE FROM `GameServer` + DELETE FROM `GameServers` WHERE `Id` = {self._id}; """ ) @@ -118,7 +136,7 @@ class GameServer(TableABC): def delete_by_user_id_string(id: int) -> str: return str( f""" - DELETE FROM `GameServer` + DELETE FROM `GameServers` WHERE `UserId` = {id} """ ) diff --git a/kdb-bot/src/bot_data/service/game_server_repository_service.py b/kdb-bot/src/bot_data/service/game_server_repository_service.py new file mode 100644 index 00000000..20f89433 --- /dev/null +++ b/kdb-bot/src/bot_data/service/game_server_repository_service.py @@ -0,0 +1,89 @@ +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.api_key_repository_abc import ApiKeyRepositoryABC +from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.model.game_server import GameServer + + +class GameServerRepositoryService(GameServerRepositoryABC): + def __init__( + self, + logger: DatabaseLogger, + db_context: DatabaseContextABC, + servers: ServerRepositoryABC, + api_keys: ApiKeyRepositoryABC, + ): + self._logger = logger + + self._context = db_context + self._servers = servers + self._api_keys = api_keys + + GameServerRepositoryABC.__init__(self) + + def _from_result(self, result: tuple): + return GameServer( + result[1], + self._servers.get_server_by_id(result[2]), + self._api_keys.get_api_key_by_id(result[3]), + result[4], + result[5], + id=result[0], + ) + + def get_game_servers(self) -> List[GameServer]: + game_servers = List(GameServer) + self._logger.trace( + __name__, + f"Send SQL command: {GameServer.get_select_all_string()}", + ) + results = self._context.select(GameServer.get_select_all_string()) + for result in results: + self._logger.trace(__name__, f"Get user-joined-game-server with id {result[0]}") + game_servers.append(self._from_result(result)) + + return game_servers + + def get_game_servers_by_server_id(self, id: int) -> List[GameServer]: + game_servers = List(GameServer) + self._logger.trace( + __name__, + f"Send SQL command: {GameServer.get_select_by_server_id_string(id)}", + ) + results = self._context.select(GameServer.get_select_by_server_id_string(id)) + for result in results: + self._logger.trace(__name__, f"Get user-joined-game-server with id {result[0]}") + game_servers.append(self._from_result(result)) + + return game_servers + + def get_game_server_by_id(self, id: int) -> GameServer: + self._logger.trace( + __name__, + f"Send SQL command: {GameServer.get_select_by_id_string(id)}", + ) + result = self._context.select(GameServer.get_select_by_id_string(id))[0] + return self._from_result(result) + + def get_game_server_by_api_key_id(self, id: int) -> GameServer: + self._logger.trace( + __name__, + f"Send SQL command: {GameServer.get_select_by_api_key_id_string(id)}", + ) + result = self._context.select(GameServer.get_select_by_api_key_id_string(id))[0] + return self._from_result(result) + + def add_game_server(self, game_server: GameServer): + self._logger.trace(__name__, f"Send SQL command: {game_server.insert_string}") + self._context.cursor.execute(game_server.insert_string) + + def update_game_server(self, game_server: GameServer): + self._logger.trace(__name__, f"Send SQL command: {game_server.udpate_string}") + self._context.cursor.execute(game_server.udpate_string) + + def delete_game_server(self, game_server: GameServer): + self._logger.trace(__name__, f"Send SQL command: {game_server.delete_string}") + self._context.cursor.execute(game_server.delete_string) diff --git a/kdb-bot/src/bot_data/service/user_joined_game_server_repository_service.py b/kdb-bot/src/bot_data/service/user_joined_game_server_repository_service.py index 131e5802..a166ce55 100644 --- a/kdb-bot/src/bot_data/service/user_joined_game_server_repository_service.py +++ b/kdb-bot/src/bot_data/service/user_joined_game_server_repository_service.py @@ -4,13 +4,11 @@ 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.api_key_repository_abc import ApiKeyRepositoryABC -from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC from bot_data.abc.user_joined_game_server_repository_abc import ( UserJoinedGameServerRepositoryABC, ) from bot_data.abc.user_repository_abc import UserRepositoryABC -from bot_data.model.game_server import GameServer from bot_data.model.user_joined_game_server import UserJoinedGameServer @@ -20,38 +18,20 @@ class UserJoinedGameServerRepositoryService(UserJoinedGameServerRepositoryABC): logger: DatabaseLogger, db_context: DatabaseContextABC, users: UserRepositoryABC, - servers: ServerRepositoryABC, - api_keys: ApiKeyRepositoryABC, + game_servers: GameServerRepositoryABC, ): self._logger = logger self._context = db_context self._users = users - self._servers = servers - self._api_keys = api_keys + self._game_servers = game_servers UserJoinedGameServerRepositoryABC.__init__(self) - def _game_server_from_id(self, id: int): - self._logger.trace( - __name__, - f"Send SQL command: {GameServer.get_select_by_id_string(id)}", - ) - result = self._context.select(GameServer.get_select_by_id_string(id))[0] - - return GameServer( - result[1], - self._servers.get_server_by_id(result[2]), - self._api_keys.get_api_key_by_id(result[3]), - result[4], - result[5], - id=result[0], - ) - def _from_result(self, result: tuple) -> UserJoinedGameServer: return UserJoinedGameServer( self._users.get_user_by_id(result[1]), - self._game_server_from_id(result[2]), + self._game_servers.get_game_server_by_id(result[2]), result[3], result[4], result[5], diff --git a/kdb-bot/src/bot_graphql/abc/query_abc.py b/kdb-bot/src/bot_graphql/abc/query_abc.py index 22a4213b..a90ccfd3 100644 --- a/kdb-bot/src/bot_graphql/abc/query_abc.py +++ b/kdb-bot/src/bot_graphql/abc/query_abc.py @@ -82,7 +82,7 @@ class QueryABC(ObjectType): break elif type(element) == AutoRoleRule: - element: AutoRole = element.auto_role + element: AutoRole = element.game_server for u in user.users: u: User = u guild = bot.get_guild(u.server.discord_id) diff --git a/kdb-bot/src/bot_graphql/filter/auto_role_rule_filter.py b/kdb-bot/src/bot_graphql/filter/auto_role_rule_filter.py index 01a90c66..b9571d8f 100644 --- a/kdb-bot/src/bot_graphql/filter/auto_role_rule_filter.py +++ b/kdb-bot/src/bot_graphql/filter/auto_role_rule_filter.py @@ -57,7 +57,7 @@ class AutoRoleRuleFilter(FilterABC): query = query.where(get_role_name) if self._auto_role is not None: - auto_roles = self._auto_role.filter(query.select(lambda x: x.auto_role)).select(lambda x: x.id) - query = query.where(lambda x: x.auto_role.id in auto_roles) + auto_roles = self._auto_role.filter(query.select(lambda x: x.game_server)).select(lambda x: x.id) + query = query.where(lambda x: x.game_server.id in auto_roles) return query diff --git a/kdb-bot/src/bot_graphql/queries/user_joined_game_server_query.py b/kdb-bot/src/bot_graphql/queries/user_joined_game_server_query.py index 6e29ec7d..854419e5 100644 --- a/kdb-bot/src/bot_graphql/queries/user_joined_game_server_query.py +++ b/kdb-bot/src/bot_graphql/queries/user_joined_game_server_query.py @@ -22,7 +22,7 @@ class UserJoinedGameServerQuery(DataQueryABC): @staticmethod def resolve_game_server(x: UserJoinedGameServer, *_): - return x.game_server + return x.game_server.name @staticmethod def resolve_user(x: UserJoinedGameServer, *_): diff --git a/kdb-bot/src/modules/base/base_module.py b/kdb-bot/src/modules/base/base_module.py index e83e2cf4..4d8c4f2d 100644 --- a/kdb-bot/src/modules/base/base_module.py +++ b/kdb-bot/src/modules/base/base_module.py @@ -8,6 +8,7 @@ from bot_core.abc.module_abc import ModuleABC from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from modules.base.abc.base_helper_abc import BaseHelperABC from modules.base.command.afk_command import AFKCommand +from modules.base.command.game_server_group import GameServerGroup from modules.base.command.help_command import HelpCommand from modules.base.command.info_command import InfoCommand from modules.base.command.mass_move_command import MassMoveCommand @@ -66,6 +67,7 @@ class BaseModule(ModuleABC): self._dc.add_command(UserGroup) self._dc.add_command(RegisterGroup) self._dc.add_command(UnregisterGroup) + self._dc.add_command(GameServerGroup) # events self._dc.add_event(DiscordEventTypesEnum.on_command.value, BaseOnCommandEvent) self._dc.add_event(DiscordEventTypesEnum.on_command_error.value, BaseOnCommandErrorEvent) diff --git a/kdb-bot/src/modules/base/command/game_server_group.py b/kdb-bot/src/modules/base/command/game_server_group.py new file mode 100644 index 00000000..7d3073be --- /dev/null +++ b/kdb-bot/src/modules/base/command/game_server_group.py @@ -0,0 +1,151 @@ +from typing import List as TList + +import discord +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.command import DiscordCommandABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_translation import TranslatePipe +from discord import app_commands +from discord.ext import commands +from discord.ext.commands import Context + +from bot_core.abc.client_utils_abc import ClientUtilsABC +from bot_core.abc.message_service_abc import MessageServiceABC +from bot_core.helper.command_checks import CommandChecks +from bot_core.logging.command_logger import CommandLogger +from bot_data.abc.api_key_repository_abc import ApiKeyRepositoryABC +from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.model.game_server import GameServer +from modules.permission.abc.permission_service_abc import PermissionServiceABC + + +class GameServerGroup(DiscordCommandABC): + def __init__( + self, + logger: CommandLogger, + message_service: MessageServiceABC, + bot: DiscordBotServiceABC, + client_utils: ClientUtilsABC, + translate: TranslatePipe, + servers: ServerRepositoryABC, + game_servers: GameServerRepositoryABC, + api_keys: ApiKeyRepositoryABC, + db: DatabaseContextABC, + permission_service: PermissionServiceABC, + ): + DiscordCommandABC.__init__(self) + + self._logger = logger + self._message_service = message_service + self._bot = bot + self._client_utils = client_utils + self._t = translate + self._servers = servers + self._game_servers = game_servers + self._api_keys = api_keys + self._db = db + self._permissions = permission_service + + self._logger.trace(__name__, f"Loaded command service: {type(self).__name__}") + + @commands.hybrid_group(name="game-server") + @commands.guild_only() + async def game_server(self, ctx: Context): + pass + + @game_server.command(alias="game-servers") + @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_moderator() + async def list(self, ctx: Context, wait: int = None): + self._logger.debug(__name__, f"Received command game_server list {ctx}") + + if ctx.guild is None: + return + + server = self._servers.get_server_by_discord_id(ctx.guild.id) + game_servers = self._game_servers.get_game_servers_by_server_id(server.id) + if game_servers.count() < 1: + await self._message_service.send_ctx_msg( + ctx, self._t.transform("modules.base.game_server.error.nothing_found") + ) + self._logger.trace(__name__, f"Finished command game_server list") + return + + game_server_name = "" + api_key = "" + for game_server in game_servers: + game_server: GameServer = game_server + game_server_name += f"\n{game_server.name}" + api_key += f"\n{game_server.api_key.identifier}" + + embed = discord.Embed( + title=self._t.transform("modules.base.game_server.list.title"), + description=self._t.transform("modules.base.game_server.list.description"), + color=int("ef9d0d", 16), + ) + embed.add_field( + name=self._t.transform("modules.base.game_server.list.name"), + value=game_server_name, + inline=True, + ) + embed.add_field(name=self._t.transform("modules.base.game_server.list.api_key"), value=api_key, inline=True) + + await self._message_service.send_ctx_msg(ctx, embed, wait_before_delete=wait) + self._logger.trace(__name__, f"Finished command game_server list") + + @game_server.command() + @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_admin() + async def add(self, ctx: Context, name: str, api_key_id: int): + self._logger.debug(__name__, f"Received command game-server add {ctx}: {name} {api_key_id}") + + server = self._servers.get_server_by_discord_id(ctx.guild.id) + api_key = self._api_keys.get_api_key_by_id(api_key_id) + game_server = GameServer(name, server, api_key) + + self._game_servers.add_game_server(game_server) + self._db.save_changes() + await self._message_service.send_ctx_msg( + ctx, + self._t.transform("modules.base.game_server.add.success").format(name), + ) + + self._logger.trace(__name__, f"Finished command game-server add") + + @add.autocomplete("api_key_id") + async def api_key_id_autocomplete( + self, interaction: discord.Interaction, current: str + ) -> TList[app_commands.Choice[str]]: + keys = self._api_keys.get_api_keys() + + return [ + app_commands.Choice(name=f"{key.identifier}: {key.key}", value=key.id) + for key in self._client_utils.get_auto_complete_list(keys, current, lambda x: x.key) + ] + + @game_server.command() + @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_admin() + async def remove(self, ctx: Context, id: int): + self._logger.debug(__name__, f"Received command game-server remove {ctx}: {id}") + + game_server = self._game_servers.get_game_server_by_id(id) + self._game_servers.delete_game_server(game_server) + self._db.save_changes() + await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.base.game_server.remove.success")) + + self._logger.trace(__name__, f"Finished command game-server remove") + + @remove.autocomplete("id") + async def id_autocomplete(self, interaction: discord.Interaction, current: str) -> TList[app_commands.Choice[str]]: + server = self._servers.get_server_by_discord_id(interaction.guild.id) + game_servers = self._game_servers.get_game_servers_by_server_id(server.id) + + return [ + app_commands.Choice(name=gs.name, value=gs.id) + for gs in self._client_utils.get_auto_complete_list(game_servers, current, lambda x: x.name) + ]