From ce85bb332a2eb3c4fab330588433ac42adf40d21 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sat, 7 Jan 2023 15:53:44 +0100 Subject: [PATCH] Improved query & filtering --- kdb-bot/src/bot_graphql/abc/filter_abc.py | 31 ++++++++++----- .../src/bot_graphql/filter/level_filter.py | 37 ++++++++++++++++++ .../src/bot_graphql/filter/server_filter.py | 9 +---- kdb-bot/src/bot_graphql/graphql_module.py | 2 + kdb-bot/src/bot_graphql/model.gql | 9 ++++- .../src/bot_graphql/queries/level_query.py | 39 +++++++++++++++++++ .../src/bot_graphql/queries/server_query.py | 15 ++++++- 7 files changed, 122 insertions(+), 20 deletions(-) create mode 100644 kdb-bot/src/bot_graphql/filter/level_filter.py create mode 100644 kdb-bot/src/bot_graphql/queries/level_query.py diff --git a/kdb-bot/src/bot_graphql/abc/filter_abc.py b/kdb-bot/src/bot_graphql/abc/filter_abc.py index 827f45b3..d2174a7d 100644 --- a/kdb-bot/src/bot_graphql/abc/filter_abc.py +++ b/kdb-bot/src/bot_graphql/abc/filter_abc.py @@ -1,6 +1,9 @@ import functools from abc import ABC from inspect import signature, Parameter +from typing import Optional + +from cpl_query.extension import List class FilterABC(ABC): @@ -8,33 +11,41 @@ class FilterABC(ABC): def __init__(self): ABC.__init__(self) - self._page_index = 0 - self._page_size = 10 - self._sort_direction = '' - self._sort_column = '' + self._page_index = None + self._page_size = None + self._sort_direction = None + self._sort_column = None @property - def page_index(self) -> int: + def page_index(self) -> Optional[int]: return self._page_index @property - def page_size(self) -> int: + def page_size(self) -> Optional[int]: return self._page_size @property - def sort_direction(self) -> str: + def sort_direction(self) -> Optional[str]: return self._sort_direction @property - def sort_column(self) -> str: + def sort_column(self) -> Optional[str]: return self._sort_column + def skip_and_take(self, query: List): + if self._page_size is not None and self.page_index is not None: + skip = self.page_size * self.page_index + result = query.skip(skip).take(self.page_size) + return result + + return query + @staticmethod def get_filter(f, values: dict): sig = signature(f) for param in sig.parameters.items(): parameter = param[1] - if parameter.name == 'self' or parameter.annotation == Parameter.empty: + if parameter.name == 'self' or parameter.name == 'cls' or parameter.annotation == Parameter.empty: continue if issubclass(parameter.annotation, FilterABC): @@ -45,7 +56,7 @@ class FilterABC(ABC): @classmethod def resolve_filter_annotation(cls, f=None): if f is None: - return functools.partial(cls.filter) + return functools.partial(cls.resolve_filter_annotation) @functools.wraps(f) def decorator(*args, **kwargs): diff --git a/kdb-bot/src/bot_graphql/filter/level_filter.py b/kdb-bot/src/bot_graphql/filter/level_filter.py new file mode 100644 index 00000000..5c0aad6d --- /dev/null +++ b/kdb-bot/src/bot_graphql/filter/level_filter.py @@ -0,0 +1,37 @@ +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.container import Guild +from cpl_discord.service import DiscordBotServiceABC +from cpl_query.extension import List + +from bot_data.model.level import Level +from bot_data.model.server import Server +from bot_graphql.abc.filter_abc import FilterABC + + +class LevelFilter(FilterABC): + + def __init__(self): + FilterABC.__init__(self) + + self._id = None + self._name = None + # self._server_id = None + + def from_dict(self, values: dict): + if 'id' in values: + self._id = values['id'] + + def filter(self, query: List[Level]) -> List[Level]: + if self._id is not None: + query = query.where(lambda x: x.id == self._id) + + if self._name is not None: + query = query.where(lambda x: self._name.lower() == x.name.lower() or self._name.lower() in x.name.lower()) + + # if self._server_id is not None: + # query = query.where(lambda x: x.server.server_id == self._server_id) + + skip = self.page_size * self.page_index + result = query.skip(skip).take(self.page_size) + + return result diff --git a/kdb-bot/src/bot_graphql/filter/server_filter.py b/kdb-bot/src/bot_graphql/filter/server_filter.py index 26fcb8ea..afa0711a 100644 --- a/kdb-bot/src/bot_graphql/filter/server_filter.py +++ b/kdb-bot/src/bot_graphql/filter/server_filter.py @@ -18,12 +18,10 @@ class ServerFilter(FilterABC): def from_dict(self, values: dict): if 'id' in values: - self._id = values['id'] + self._id = int(values['id']) @ServiceProviderABC.inject def filter(self, query: List[Server], bot: DiscordBotServiceABC) -> List[Server]: - result = List(Server) - if self._id is not None: query = query.where(lambda x: x.server_id == self._id) @@ -37,7 +35,4 @@ class ServerFilter(FilterABC): query = query.where(where_guild) - skip = self.page_size * self.page_index - result = query.skip(skip).take(self.page_size) - - return result + return self.skip_and_take(query) diff --git a/kdb-bot/src/bot_graphql/graphql_module.py b/kdb-bot/src/bot_graphql/graphql_module.py index 59aa3ec4..4678a4c1 100644 --- a/kdb-bot/src/bot_graphql/graphql_module.py +++ b/kdb-bot/src/bot_graphql/graphql_module.py @@ -8,6 +8,7 @@ from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from bot_data.service.seeder_service import SeederService from bot_graphql.abc.query_abc import QueryABC from bot_graphql.graphql_service import GraphQLService +from bot_graphql.queries.level_query import LevelQuery from bot_graphql.queries.server_query import ServerQuery from bot_graphql.query import Query from bot_graphql.schema import Schema @@ -27,5 +28,6 @@ class GraphQLModule(ModuleABC): services.add_singleton(GraphQLService) services.add_singleton(Query) services.add_transient(QueryABC, ServerQuery) + services.add_transient(QueryABC, LevelQuery) services.add_transient(SeederService) diff --git a/kdb-bot/src/bot_graphql/model.gql b/kdb-bot/src/bot_graphql/model.gql index 94182271..93843058 100644 --- a/kdb-bot/src/bot_graphql/model.gql +++ b/kdb-bot/src/bot_graphql/model.gql @@ -10,7 +10,7 @@ interface TableQuery { } input ServerFilter { - id: Int + id: ID discord_id: String name: String @@ -26,7 +26,7 @@ type Server implements TableQuery { name: String clients: [Client] members: [User] - level: [Level] + levels: [Level] created_at: String modified_at: String @@ -86,6 +86,11 @@ type UserJoinedVoiceChannel implements TableQuery { modified_at: String } +input LevelFilter { + id: ID + name: String +} + type Level implements TableQuery { id: ID name: String diff --git a/kdb-bot/src/bot_graphql/queries/level_query.py b/kdb-bot/src/bot_graphql/queries/level_query.py new file mode 100644 index 00000000..0f19aa81 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/level_query.py @@ -0,0 +1,39 @@ +from bot_data.model.level import Level +from bot_graphql.abc.data_query_abc import DataQueryABC + + +class LevelQuery(DataQueryABC): + + def __init__(self): + DataQueryABC.__init__(self, 'Level') + + self.set_field('id', self.resolve_id) + self.set_field('name', self.resolve_name) + self.set_field('color', self.resolve_color) + self.set_field('min_xp', self.resolve_min_xp) + self.set_field('permissions', self.resolve_permissions) + self.set_field('server', self.resolve_server) + + @staticmethod + def resolve_id(level: Level, *_): + return level.id + + @staticmethod + def resolve_name(level: Level, *_): + return level.name + + @staticmethod + def resolve_color(level: Level, *_): + return level.color + + @staticmethod + def resolve_min_xp(level: Level, *_): + return level.min_xp + + @staticmethod + def resolve_permissions(level: Level, *_): + return level.permissions + + @staticmethod + def resolve_server(level: Level, *_): + return level.server diff --git a/kdb-bot/src/bot_graphql/queries/server_query.py b/kdb-bot/src/bot_graphql/queries/server_query.py index 81a1a2ac..2c54692c 100644 --- a/kdb-bot/src/bot_graphql/queries/server_query.py +++ b/kdb-bot/src/bot_graphql/queries/server_query.py @@ -1,22 +1,28 @@ from cpl_discord.service import DiscordBotServiceABC +from bot_data.abc.level_repository_abc import LevelRepositoryABC from bot_data.model.server import Server from bot_graphql.abc.data_query_abc import DataQueryABC +from bot_graphql.abc.filter_abc import FilterABC +from bot_graphql.filter.level_filter import LevelFilter class ServerQuery(DataQueryABC): def __init__( self, - bot: DiscordBotServiceABC + bot: DiscordBotServiceABC, + levels: LevelRepositoryABC, ): DataQueryABC.__init__(self, 'Server') self._bot = bot + 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('levels', self.resolve_levels) @staticmethod def resolve_id(server: Server, *_): @@ -29,3 +35,10 @@ class ServerQuery(DataQueryABC): def resolve_name(self, server: Server, *_): guild = self._bot.get_guild(server.discord_server_id) return None if guild is None else guild.name + + @FilterABC.resolve_filter_annotation + def resolve_levels(self, server: Server, *_, filter: LevelFilter = None): + if filter is not None: + return filter.filter(self._levels.get_levels_by_server_id(server.server_id)) + + return self._levels.get_levels_by_server_id(server.server_id)