From b9e66bba9d0d83e4adb52bbf3bce280571690e2f Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 15 Jan 2023 10:36:00 +0100 Subject: [PATCH] Added more queries #162 --- kdb-bot/.cpl/schematic_query.py | 34 ++++++++++ kdb-bot/src/bot/bot.json | 2 +- .../src/bot_data/abc/client_repository_abc.py | 5 ++ .../src/bot_data/abc/user_repository_abc.py | 4 ++ kdb-bot/src/bot_data/model/user.py | 10 +++ .../service/client_repository_service.py | 22 ++++++ .../service/user_repository_service.py | 19 ++++++ kdb-bot/src/bot_graphql/graphql_module.py | 9 ++- .../src/bot_graphql/queries/client_query.py | 59 ++++++++++++++++ .../src/bot_graphql/queries/server_query.py | 14 ++++ .../queries/user_joined_server_query.py | 33 +++++++++ .../user_joined_voice_channel_query.py | 38 +++++++++++ kdb-bot/src/bot_graphql/queries/user_query.py | 67 +++++++++++++++++++ 13 files changed, 314 insertions(+), 2 deletions(-) create mode 100644 kdb-bot/.cpl/schematic_query.py create mode 100644 kdb-bot/src/bot_graphql/queries/client_query.py create mode 100644 kdb-bot/src/bot_graphql/queries/user_joined_server_query.py create mode 100644 kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_query.py create mode 100644 kdb-bot/src/bot_graphql/queries/user_query.py diff --git a/kdb-bot/.cpl/schematic_query.py b/kdb-bot/.cpl/schematic_query.py new file mode 100644 index 00000000..e34a3b6e --- /dev/null +++ b/kdb-bot/.cpl/schematic_query.py @@ -0,0 +1,34 @@ +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class query(GenerateSchematicABC): + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + import textwrap + + code = textwrap.dedent( + """\ + from bot_graphql.abc.data_query_abc import DataQueryABC + + + class $ClassName(DataQueryABC): + def __init__(self): + DataQueryABC.__init__(self, "Name") + + self.set_field("id", self.resolve_id) + + @staticmethod + def resolve_id(x, *_): + return x.id + """ + ) + return self.build_code_str( + code, + ClassName=self._class_name, + ) + + @classmethod + def register(cls): + GenerateSchematicABC.register(cls, "query", []) diff --git a/kdb-bot/src/bot/bot.json b/kdb-bot/src/bot/bot.json index 4dedb3dc..2245c518 100644 --- a/kdb-bot/src/bot/bot.json +++ b/kdb-bot/src/bot/bot.json @@ -32,7 +32,7 @@ "ariadne==0.17.1" ], "DevDependencies": [ - "cpl-cli==2022.12.1.post2" + "cpl-cli==2022.12.1.post3" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, diff --git a/kdb-bot/src/bot_data/abc/client_repository_abc.py b/kdb-bot/src/bot_data/abc/client_repository_abc.py index 97d34e13..3b9f9132 100644 --- a/kdb-bot/src/bot_data/abc/client_repository_abc.py +++ b/kdb-bot/src/bot_data/abc/client_repository_abc.py @@ -2,6 +2,7 @@ from abc import ABC, abstractmethod from typing import Optional from cpl_query.extension import List + from bot_data.model.client import Client @@ -22,6 +23,10 @@ class ClientRepositoryABC(ABC): def get_client_by_discord_id(self, discord_id: int) -> Client: pass + @abstractmethod + def get_clients_by_server_id(self, server_id: int) -> List[Client]: + pass + @abstractmethod def find_client_by_discord_id(self, discord_id: int) -> Optional[Client]: pass diff --git a/kdb-bot/src/bot_data/abc/user_repository_abc.py b/kdb-bot/src/bot_data/abc/user_repository_abc.py index c40f20e5..0e3ced21 100644 --- a/kdb-bot/src/bot_data/abc/user_repository_abc.py +++ b/kdb-bot/src/bot_data/abc/user_repository_abc.py @@ -27,6 +27,10 @@ class UserRepositoryABC(ABC): def get_users_by_discord_id(self, discord_id: int) -> List[User]: pass + @abstractmethod + def get_users_by_server_id(self, server_id: int) -> List[User]: + pass + @abstractmethod def get_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> User: pass diff --git a/kdb-bot/src/bot_data/model/user.py b/kdb-bot/src/bot_data/model/user.py index 1592e471..ab97ecd1 100644 --- a/kdb-bot/src/bot_data/model/user.py +++ b/kdb-bot/src/bot_data/model/user.py @@ -1,5 +1,6 @@ from datetime import datetime from typing import Optional + from cpl_core.database import TableABC from bot_data.model.server import Server @@ -62,6 +63,15 @@ class User(TableABC): """ ) + @staticmethod + def get_select_by_server_id_string(server_id: int) -> str: + return str( + f""" + SELECT * FROM `Users` + WHERE `ServerId` = {server_id}; + """ + ) + @staticmethod def get_select_by_discord_id_string(id: int) -> str: return str( diff --git a/kdb-bot/src/bot_data/service/client_repository_service.py b/kdb-bot/src/bot_data/service/client_repository_service.py index aca04447..51d3b6cf 100644 --- a/kdb-bot/src/bot_data/service/client_repository_service.py +++ b/kdb-bot/src/bot_data/service/client_repository_service.py @@ -62,6 +62,28 @@ class ClientRepositoryService(ClientRepositoryABC): id=result[0], ) + def get_clients_by_server_id(self, server_id: int) -> List[Client]: + clients = List(Client) + self._logger.trace(__name__, f"Send SQL command: {Client.get_select_by_server_id_string(server_id)}") + results = self._context.select(Client.get_select_by_server_id_string(server_id)) + for result in results: + clients.append( + Client( + result[1], + result[2], + result[3], + result[4], + result[5], + result[6], + self._servers.get_server_by_id(result[7]), + result[8], + result[9], + id=result[0], + ) + ) + + return clients + def get_client_by_discord_id(self, discord_id: int) -> Client: self._logger.trace( __name__, diff --git a/kdb-bot/src/bot_data/service/user_repository_service.py b/kdb-bot/src/bot_data/service/user_repository_service.py index 00ee4a64..9d44c0ba 100644 --- a/kdb-bot/src/bot_data/service/user_repository_service.py +++ b/kdb-bot/src/bot_data/service/user_repository_service.py @@ -85,6 +85,25 @@ class UserRepositoryService(UserRepositoryABC): return users + def get_users_by_server_id(self, server_id: int) -> List[User]: + users = List(User) + self._logger.trace( + __name__, + f"Send SQL command: {User.get_select_by_server_id_string(server_id)}", + ) + results = self._context.select(User.get_select_by_server_id_string(server_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__, diff --git a/kdb-bot/src/bot_graphql/graphql_module.py b/kdb-bot/src/bot_graphql/graphql_module.py index a06ad96e..37ca29fd 100644 --- a/kdb-bot/src/bot_graphql/graphql_module.py +++ b/kdb-bot/src/bot_graphql/graphql_module.py @@ -10,8 +10,12 @@ from bot_graphql.abc.query_abc import QueryABC from bot_graphql.graphql_service import GraphQLService from bot_graphql.mutation import Mutation from bot_graphql.mutations.level_mutation import LevelMutation +from bot_graphql.queries.client_query import ClientQuery from bot_graphql.queries.level_query import LevelQuery from bot_graphql.queries.server_query import ServerQuery +from bot_graphql.queries.user_joined_server_query import UserJoinedServerQuery +from bot_graphql.queries.user_joined_voice_channel_query import UserJoinedVoiceChannelQuery +from bot_graphql.queries.user_query import UserQuery from bot_graphql.query import Query from bot_graphql.schema import Schema @@ -24,7 +28,6 @@ class GraphQLModule(ModuleABC): pass def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): - services.add_singleton(Schema) services.add_singleton(GraphQLService) services.add_singleton(Query) @@ -32,5 +35,9 @@ class GraphQLModule(ModuleABC): services.add_transient(QueryABC, ServerQuery) services.add_transient(QueryABC, LevelQuery) services.add_transient(QueryABC, LevelMutation) + services.add_transient(QueryABC, ClientQuery) + services.add_transient(QueryABC, UserQuery) + services.add_transient(QueryABC, UserJoinedServerQuery) + services.add_transient(QueryABC, UserJoinedVoiceChannelQuery) services.add_transient(SeederService) diff --git a/kdb-bot/src/bot_graphql/queries/client_query.py b/kdb-bot/src/bot_graphql/queries/client_query.py new file mode 100644 index 00000000..6460dc54 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/client_query.py @@ -0,0 +1,59 @@ +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.model.client import Client +from bot_graphql.abc.data_query_abc import DataQueryABC + + +class ClientQuery(DataQueryABC): + def __init__( + self, + bot: DiscordBotServiceABC, + ): + DataQueryABC.__init__(self, "Client") + + self._bot = bot + + self.set_field("id", self.resolve_id) + self.set_field("discord_id", self.resolve_discord_id) + self.set_field("name", self.resolve_name) + self.set_field("sent_message_count", self.resolve_sent_message_count) + self.set_field("received_message_count", self.resolve_received_message_count) + self.set_field("deleted_message_count", self.resolve_deleted_message_count) + self.set_field("received_command_count", self.resolve_received_command_count) + self.set_field("moved_users_count", self.resolve_moved_users_count) + self.set_field("server", self.resolve_server) + + @staticmethod + def resolve_id(client: Client, *_): + return client.client_id + + @staticmethod + def resolve_discord_id(client: Client, *_): + return client.discord_id + + def resolve_name(self, client: Client, *_): + return self._bot.user.name + + @staticmethod + def resolve_sent_message_count(client: Client, *_): + return client.sent_message_count + + @staticmethod + def resolve_received_message_count(client: Client, *_): + return client.received_command_count + + @staticmethod + def resolve_deleted_message_count(client: Client, *_): + return client.deleted_message_count + + @staticmethod + def resolve_received_command_count(client: Client, *_): + return client.received_command_count + + @staticmethod + def resolve_moved_users_count(client: Client, *_): + return client.moved_users_count + + @staticmethod + def resolve_server(client: Client, *_): + return client.server diff --git a/kdb-bot/src/bot_graphql/queries/server_query.py b/kdb-bot/src/bot_graphql/queries/server_query.py index 92b308e8..bfcfebbc 100644 --- a/kdb-bot/src/bot_graphql/queries/server_query.py +++ b/kdb-bot/src/bot_graphql/queries/server_query.py @@ -1,6 +1,8 @@ from cpl_discord.service import DiscordBotServiceABC +from bot_data.abc.client_repository_abc import ClientRepositoryABC from bot_data.abc.level_repository_abc import LevelRepositoryABC +from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.model.server import Server from bot_graphql.abc.data_query_abc import DataQueryABC from bot_graphql.abc.filter_abc import FilterABC @@ -11,16 +13,22 @@ class ServerQuery(DataQueryABC): def __init__( self, bot: DiscordBotServiceABC, + clients: ClientRepositoryABC, + users: UserRepositoryABC, levels: LevelRepositoryABC, ): DataQueryABC.__init__(self, "Server") self._bot = bot + self._clients = clients + self._users = users self._levels = levels self.set_field("id", self.resolve_id) self.set_field("discord_id", self.resolve_discord_id) self.set_field("name", self.resolve_name) + self.set_field("clients", self.resolve_clients) + self.set_field("members", self.resolve_members) self.set_field("levels", self.resolve_levels) @staticmethod @@ -35,6 +43,12 @@ class ServerQuery(DataQueryABC): guild = self._bot.get_guild(server.discord_server_id) return None if guild is None else guild.name + def resolve_clients(self, server: Server, *_): + return self._clients.get_clients_by_server_id(server.server_id) + + def resolve_members(self, server: Server, *_): + return self._users.get_users_by_server_id(server.server_id) + @FilterABC.resolve_filter_annotation def resolve_levels(self, server: Server, *_, filter: LevelFilter = None): if filter is not None: diff --git a/kdb-bot/src/bot_graphql/queries/user_joined_server_query.py b/kdb-bot/src/bot_graphql/queries/user_joined_server_query.py new file mode 100644 index 00000000..ef9ebda2 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/user_joined_server_query.py @@ -0,0 +1,33 @@ +from bot_data.model.user_joined_server import UserJoinedServer +from bot_graphql.abc.data_query_abc import DataQueryABC + + +class UserJoinedServerQuery(DataQueryABC): + def __init__(self): + DataQueryABC.__init__(self, "UserJoinedServer") + + self.set_field("id", self.resolve_id) + self.set_field("user", self.resolve_user) + self.set_field("server", self.resolve_server) + self.set_field("joined_on", self.resolve_joined_on) + self.set_field("leaved_on", self.resolve_leaved_on) + + @staticmethod + def resolve_id(x: UserJoinedServer, *_): + return x.join_id + + @staticmethod + def resolve_user(x: UserJoinedServer, *_): + return x.user + + @staticmethod + def resolve_server(x: UserJoinedServer, *_): + return x.user.server + + @staticmethod + def resolve_joined_on(x: UserJoinedServer, *_): + return x.joined_on + + @staticmethod + def resolve_leaved_on(x: UserJoinedServer, *_): + return x.leaved_on diff --git a/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_query.py b/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_query.py new file mode 100644 index 00000000..f4d18a32 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_query.py @@ -0,0 +1,38 @@ +from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel +from bot_graphql.abc.data_query_abc import DataQueryABC + + +class UserJoinedVoiceChannelQuery(DataQueryABC): + def __init__(self): + DataQueryABC.__init__(self, "UserJoinedVoiceChannel") + + self.set_field("id", self.resolve_id) + self.set_field("channel_id", self.resolve_channel_id) + self.set_field("user", self.resolve_user) + self.set_field("server", self.resolve_server) + self.set_field("joined_on", self.resolve_joined_on) + self.set_field("leaved_on", self.resolve_leaved_on) + + @staticmethod + def resolve_id(x: UserJoinedVoiceChannel, *_): + return x.join_id + + @staticmethod + def resolve_channel_id(x: UserJoinedVoiceChannel, *_): + return x.dc_channel_id + + @staticmethod + def resolve_user(x: UserJoinedVoiceChannel, *_): + return x.user + + @staticmethod + def resolve_server(x: UserJoinedVoiceChannel, *_): + return x.user.server + + @staticmethod + def resolve_joined_on(x: UserJoinedVoiceChannel, *_): + return x.joined_on + + @staticmethod + def resolve_leaved_on(x: UserJoinedVoiceChannel, *_): + return x.leaved_on diff --git a/kdb-bot/src/bot_graphql/queries/user_query.py b/kdb-bot/src/bot_graphql/queries/user_query.py new file mode 100644 index 00000000..0e10d7da --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/user_query.py @@ -0,0 +1,67 @@ +from cpl_discord.service import DiscordBotServiceABC + +from bot_core.abc.client_utils_abc import ClientUtilsABC +from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC +from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC +from bot_data.model.user import User +from bot_graphql.abc.data_query_abc import DataQueryABC +from modules.level.service.level_service import LevelService + + +class UserQuery(DataQueryABC): + def __init__( + self, + bot: DiscordBotServiceABC, + levels: LevelService, + client_utils: ClientUtilsABC, + ujs: UserJoinedServerRepositoryABC, + ujvs: UserJoinedVoiceChannelRepositoryABC, + ): + DataQueryABC.__init__(self, "User") + + self._bot = bot + self._levels = levels + self._client_utils = client_utils + self._ujs = ujs + self._ujvs = ujvs + + self.set_field("id", self.resolve_id) + self.set_field("discord_id", self.resolve_discord_id) + self.set_field("name", self.resolve_name) + self.set_field("xp", self.resolve_xp) + self.set_field("ontime", self.resolve_ontime) + self.set_field("level", self.resolve_level) + self.set_field("joined_servers", self.resolve_joined_servers) + self.set_field("joined_voice_channel", self.resolve_joined_voice_channel) + self.set_field("server", self.resolve_server) + + @staticmethod + def resolve_id(user: User, *_): + return user.user_id + + @staticmethod + def resolve_discord_id(user: User, *_): + return user.discord_id + + def resolve_name(self, user: User, *_): + return self._bot.get_guild(user.server.discord_server_id).get_member(user.discord_id).name + + @staticmethod + def resolve_xp(user: User, *_): + return user.xp + + def resolve_ontime(self, user: User, *_): + return self._client_utils.get_ontime_for_user(user) + + def resolve_level(self, user: User, *_): + return self._levels.get_level(user) + + def resolve_joined_servers(self, user: User, *_): + return self._ujs.get_user_joined_servers_by_user_id(user.user_id) + + def resolve_joined_voice_channel(self, user: User, *_): + return self._ujvs.get_user_joined_voice_channels_by_user_id(user.user_id) + + @staticmethod + def resolve_server(user: User, *_): + return user.server