Improved queries & filtering #162
This commit is contained in:
parent
c75cc54d16
commit
807827e30f
@ -1 +1 @@
|
||||
Subproject commit 54b1b3860cb570d29c8ba2590dd082a1fa744265
|
||||
Subproject commit b0ae87621bbe54fd9c5650071ec8c1c9ec32df48
|
@ -3,7 +3,6 @@ from ariadne.constants import PLAYGROUND_HTML
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.environment import ApplicationEnvironmentABC
|
||||
from flask import request, jsonify
|
||||
from graphql import MiddlewareManager
|
||||
|
||||
from bot_api.logging.api_logger import ApiLogger
|
||||
from bot_api.route.route import Route
|
||||
|
20
kdb-bot/src/bot_graphql/abc/discord_query_type_abc.py
Normal file
20
kdb-bot/src/bot_graphql/abc/discord_query_type_abc.py
Normal file
@ -0,0 +1,20 @@
|
||||
from datetime import datetime
|
||||
|
||||
from bot_graphql.abc.query_type_abc import QueryTypeABC
|
||||
|
||||
|
||||
class DiscordQueryTypeABC(QueryTypeABC):
|
||||
def __init__(
|
||||
self,
|
||||
id: str,
|
||||
discord_id: str,
|
||||
created_at: datetime = None,
|
||||
modified_at: datetime = None,
|
||||
):
|
||||
QueryTypeABC.__init__(self, id, created_at, modified_at)
|
||||
|
||||
self._discord_id = discord_id
|
||||
|
||||
@property
|
||||
def discord_id(self) -> str:
|
||||
return self._discord_id
|
@ -1,5 +1,5 @@
|
||||
import functools
|
||||
from abc import ABC
|
||||
from abc import ABC, abstractmethod
|
||||
from inspect import signature, Parameter
|
||||
from typing import Optional
|
||||
|
||||
@ -40,6 +40,14 @@ class FilterABC(ABC):
|
||||
|
||||
return query
|
||||
|
||||
@abstractmethod
|
||||
def from_dict(self, values: dict):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def filter(self, query: List, *args) -> List:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
@ServiceProviderABC.inject
|
||||
def get_filter(f, values: dict, services: ServiceProviderABC):
|
||||
@ -52,7 +60,14 @@ class FilterABC(ABC):
|
||||
if issubclass(parameter.annotation, FilterABC):
|
||||
filter = services.get_service(parameter.annotation)
|
||||
filter.from_dict(values)
|
||||
return filter
|
||||
return filter @ staticmethod
|
||||
|
||||
@staticmethod
|
||||
@ServiceProviderABC.inject
|
||||
def get_collection_filter(filter_type: type, values: dict, services: ServiceProviderABC):
|
||||
filter: FilterABC = services.get_service(filter_type)
|
||||
filter.from_dict(values)
|
||||
return filter
|
||||
|
||||
@classmethod
|
||||
def resolve_filter_annotation(cls, f=None):
|
||||
|
@ -1,5 +1,30 @@
|
||||
from typing import Callable
|
||||
|
||||
from ariadne import ObjectType
|
||||
from cpl_query.extension import List
|
||||
|
||||
from bot_graphql.abc.filter_abc import FilterABC
|
||||
|
||||
|
||||
class QueryABC(ObjectType):
|
||||
__abstract__ = True
|
||||
|
||||
def __init__(self, name: str):
|
||||
ObjectType.__init__(self, name)
|
||||
|
||||
def _add_collection(self, name: str, get_collection: Callable, filter_type: type = None):
|
||||
def wrapper(*args, **kwargs):
|
||||
if filter_type is not None and "filter" in kwargs:
|
||||
kwargs["filter"] = FilterABC.get_collection_filter(filter_type, kwargs["filter"])
|
||||
else:
|
||||
kwargs["filter"] = None
|
||||
|
||||
return self._resolve_collection(get_collection(*args), *args, **kwargs)
|
||||
|
||||
self.set_field(f"{name}s", wrapper)
|
||||
self.set_field(f"{name}_count", lambda *args: get_collection(*args).count())
|
||||
|
||||
def _resolve_collection(self, collection: List, *_, filter: FilterABC = None):
|
||||
if filter is not None:
|
||||
return filter.filter(collection)
|
||||
return collection
|
||||
|
29
kdb-bot/src/bot_graphql/abc/query_type_abc.py
Normal file
29
kdb-bot/src/bot_graphql/abc/query_type_abc.py
Normal file
@ -0,0 +1,29 @@
|
||||
from abc import ABC
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class QueryTypeABC(ABC):
|
||||
def __init__(
|
||||
self,
|
||||
id: str,
|
||||
created_at: datetime = None,
|
||||
modified_at: datetime = None,
|
||||
):
|
||||
ABC.__init__(self)
|
||||
|
||||
self._id = id
|
||||
self._created_at = created_at
|
||||
self._modified_at = modified_at
|
||||
|
||||
@property
|
||||
def id(self) -> str:
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def created_at(self) -> Optional[datetime]:
|
||||
return self._created_at
|
||||
|
||||
@property
|
||||
def modified_at(self) -> Optional[datetime]:
|
||||
return self._modified_at
|
@ -1,15 +1,25 @@
|
||||
from cpl_discord.service import DiscordBotServiceABC
|
||||
from cpl_query.extension import List
|
||||
|
||||
from bot_core.abc.client_utils_abc import ClientUtilsABC
|
||||
from bot_data.model.user import User
|
||||
from bot_graphql.abc.filter_abc import FilterABC
|
||||
from modules.level.service.level_service import LevelService
|
||||
|
||||
|
||||
class UserFilter(FilterABC):
|
||||
def __init__(
|
||||
self,
|
||||
bot: DiscordBotServiceABC,
|
||||
client_utils: ClientUtilsABC,
|
||||
levels: LevelService,
|
||||
):
|
||||
FilterABC.__init__(self)
|
||||
|
||||
self._bot = bot
|
||||
self._client_utils = client_utils
|
||||
self._levels = levels
|
||||
|
||||
self._id = None
|
||||
self._discord_id = None
|
||||
self._name = None
|
||||
@ -38,10 +48,19 @@ class UserFilter(FilterABC):
|
||||
if self._discord_id is not None:
|
||||
query = query.where(lambda x: x.discord_id == self._discord_id)
|
||||
|
||||
if self._name is not None:
|
||||
query = query.where(
|
||||
lambda x: self._bot.get_user(x.discord_id).name == self._name
|
||||
or self._name in self._bot.get_user(x.discord_id).name
|
||||
)
|
||||
|
||||
if self._xp is not None:
|
||||
query = query.where(lambda x: x.xp == self._xp)
|
||||
|
||||
# if self._ontime is not None:
|
||||
# query = query.where(lambda x: self._client_utils.get_ontime_for_user(x) == self._ontime)
|
||||
if self._ontime is not None:
|
||||
query = query.where(lambda x: self._client_utils.get_ontime_for_user(x) == self._ontime)
|
||||
|
||||
if self._level is not None:
|
||||
query = query.where(lambda x: self._levels.get_level(x) == self._level)
|
||||
|
||||
return self.skip_and_take(query)
|
||||
|
@ -8,11 +8,32 @@ type Mutation {
|
||||
}
|
||||
|
||||
type Query {
|
||||
servers(filter: ServerFilter): [Server]
|
||||
server_count: Int
|
||||
auto_roles: [AutoRole]
|
||||
auto_role_count: Int
|
||||
|
||||
auto_role_rules: [AutoRole]
|
||||
auto_role_rule_count: Int
|
||||
|
||||
clients: [Client]
|
||||
client_count: Int
|
||||
|
||||
known_users: [KnownUser]
|
||||
known_user_count: Int
|
||||
|
||||
levels: [Level]
|
||||
level_count: Int
|
||||
|
||||
servers(filter: ServerFilter): [Server]
|
||||
server_count: Int
|
||||
|
||||
user_joined_servers: [User]
|
||||
user_joined_server_count: Int
|
||||
|
||||
user_joined_voice_channels: [User]
|
||||
user_joined_voice_channel_count: Int
|
||||
|
||||
users(filter: UserFilter): [User]
|
||||
user_count: Int
|
||||
}
|
||||
|
||||
type KnownUser implements TableQuery {
|
||||
@ -38,10 +59,18 @@ type Server implements TableQuery {
|
||||
id: ID
|
||||
discord_id: String
|
||||
name: String
|
||||
|
||||
auto_roles: [AutoRole]
|
||||
auto_role_count: Int
|
||||
|
||||
clients: [Client]
|
||||
members: [User]
|
||||
client_count: Int
|
||||
|
||||
users(filter: UserFilter): [User]
|
||||
user_count: Int
|
||||
|
||||
levels: [Level]
|
||||
level_count: Int
|
||||
|
||||
created_at: String
|
||||
modified_at: String
|
||||
@ -69,7 +98,9 @@ type AutoRole implements TableQuery {
|
||||
message_id: String
|
||||
|
||||
server: Server
|
||||
rules: [AutoRoleRule]
|
||||
|
||||
auto_role_rules: [AutoRoleRule]
|
||||
auto_role_rule_count: Int
|
||||
|
||||
created_at: String
|
||||
modified_at: String
|
||||
@ -109,7 +140,10 @@ type User implements TableQuery {
|
||||
level: Level
|
||||
|
||||
joined_servers: [UserJoinedServer]
|
||||
joined_server_count: Int
|
||||
|
||||
joined_voice_channels: [UserJoinedVoiceChannel]
|
||||
joined_voice_channel_count: Int
|
||||
|
||||
server: Server
|
||||
|
||||
|
@ -2,7 +2,6 @@ from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC
|
||||
from bot_data.abc.server_repository_abc import ServerRepositoryABC
|
||||
from bot_data.model.auto_role import AutoRole
|
||||
from bot_graphql.abc.data_query_abc import DataQueryABC
|
||||
from bot_graphql.filter.auto_role_rule_filter import AutoRoleRuleFilter
|
||||
from bot_graphql.filter.server_filter import ServerFilter
|
||||
|
||||
|
||||
@ -21,7 +20,9 @@ class AutoRoleQuery(DataQueryABC):
|
||||
self.set_field("channel_id", self.resolve_channel_id)
|
||||
self.set_field("message_id", self.resolve_message_id)
|
||||
self.set_field("server", self.resolve_server)
|
||||
self.set_field("rules", self.resolve_rules)
|
||||
self._add_collection(
|
||||
"auto_role_rule", lambda x, *_: self._auto_role_rules.get_auto_role_rules_by_auto_role_id(x.auto_role_id)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def resolve_id(x: AutoRole, *_):
|
||||
@ -40,9 +41,3 @@ class AutoRoleQuery(DataQueryABC):
|
||||
return filter.filter(self._servers.get_server_by_id(x.server_id))
|
||||
|
||||
return self._servers.get_server_by_id(x.server_id)
|
||||
|
||||
def resolve_rules(self, x: AutoRole, *_, filter: AutoRoleRuleFilter = None):
|
||||
if filter is not None:
|
||||
return filter.filter(self._auto_role_rules.get_auto_role_rules_by_auto_role_id(x.auto_role_id))
|
||||
|
||||
return self._auto_role_rules.get_auto_role_rules_by_auto_role_id(x.auto_role_id)
|
||||
|
@ -6,9 +6,6 @@ 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
|
||||
from bot_graphql.filter.auto_role_filter import AutoRoleFilter
|
||||
from bot_graphql.filter.level_filter import LevelFilter
|
||||
from bot_graphql.filter.user_filter import UserFilter
|
||||
|
||||
|
||||
@ -33,10 +30,15 @@ class ServerQuery(DataQueryABC):
|
||||
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("auto_roles", self.resolve_auto_roles)
|
||||
self.set_field("clients", self.resolve_clients)
|
||||
self.set_field("members", self.resolve_members)
|
||||
self.set_field("levels", self.resolve_levels)
|
||||
|
||||
self._add_collection(
|
||||
"auto_role", lambda server, *_: self._auto_roles.get_auto_roles_by_server_id(server.server_id)
|
||||
)
|
||||
self._add_collection("client", lambda server, *_: self._clients.get_clients_by_server_id(server.server_id))
|
||||
self._add_collection(
|
||||
"user", lambda server, *_: self._users.get_users_by_server_id(server.server_id), UserFilter
|
||||
)
|
||||
self._add_collection("level", lambda server, *_: self._levels.get_levels_by_server_id(server.server_id))
|
||||
|
||||
@staticmethod
|
||||
def resolve_id(server: Server, *_):
|
||||
@ -49,26 +51,3 @@ 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
|
||||
|
||||
def resolve_auto_roles(self, server: Server, *_, filter: AutoRoleFilter = None):
|
||||
if filter is not None:
|
||||
return filter.filter(self._auto_roles.get_auto_roles_by_server_id(server.server_id))
|
||||
|
||||
return self._auto_roles.get_auto_roles_by_server_id(server.server_id)
|
||||
|
||||
def resolve_clients(self, server: Server, *_):
|
||||
return self._clients.get_clients_by_server_id(server.server_id)
|
||||
|
||||
@FilterABC.resolve_filter_annotation
|
||||
def resolve_members(self, server: Server, *_, filter: UserFilter = None):
|
||||
if filter is not None:
|
||||
return filter.filter(self._users.get_users_by_server_id(server.server_id))
|
||||
|
||||
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:
|
||||
return filter.filter(self._levels.get_levels_by_server_id(server.server_id))
|
||||
|
||||
return self._levels.get_levels_by_server_id(server.server_id)
|
||||
|
@ -31,8 +31,12 @@ class UserQuery(DataQueryABC):
|
||||
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_channels", self.resolve_joined_voice_channel)
|
||||
self._add_collection(
|
||||
"joined_server", lambda user, *_: self._ujs.get_user_joined_servers_by_user_id(user.user_id)
|
||||
)
|
||||
self._add_collection(
|
||||
"joined_voice_channel", lambda user, *_: self._ujvs.get_user_joined_voice_channels_by_user_id(user.user_id)
|
||||
)
|
||||
self.set_field("server", self.resolve_server)
|
||||
|
||||
@staticmethod
|
||||
@ -58,12 +62,6 @@ class UserQuery(DataQueryABC):
|
||||
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
|
||||
|
@ -1,39 +1,49 @@
|
||||
from ariadne import QueryType
|
||||
|
||||
from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC
|
||||
from bot_data.abc.client_repository_abc import ClientRepositoryABC
|
||||
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
|
||||
from bot_graphql.abc.filter_abc import FilterABC
|
||||
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.abc.user_repository_abc import UserRepositoryABC
|
||||
from bot_graphql.abc.query_abc import QueryABC
|
||||
from bot_graphql.filter.auto_role_filter import AutoRoleFilter
|
||||
from bot_graphql.filter.auto_role_rule_filter import AutoRoleRuleFilter
|
||||
from bot_graphql.filter.level_filter import LevelFilter
|
||||
from bot_graphql.filter.server_filter import ServerFilter
|
||||
from bot_graphql.filter.user_filter import UserFilter
|
||||
|
||||
|
||||
class Query(QueryType):
|
||||
class Query(QueryABC):
|
||||
def __init__(
|
||||
self,
|
||||
servers: ServerRepositoryABC,
|
||||
auto_roles: AutoRoleRepositoryABC,
|
||||
clients: ClientRepositoryABC,
|
||||
known_users: KnownUserRepositoryABC,
|
||||
levels: LevelRepositoryABC,
|
||||
servers: ServerRepositoryABC,
|
||||
user_joined_servers: UserJoinedServerRepositoryABC,
|
||||
user_joined_voice_channel: UserJoinedVoiceChannelRepositoryABC,
|
||||
users: UserRepositoryABC,
|
||||
):
|
||||
QueryType.__init__(self)
|
||||
self._servers = servers
|
||||
QueryABC.__init__(self, "Query")
|
||||
self._auto_roles = auto_roles
|
||||
self._clients = clients
|
||||
self._known_users = known_users
|
||||
self._levels = levels
|
||||
self._servers = servers
|
||||
self._user_joined_servers = user_joined_servers
|
||||
self._user_joined_voice_channels = user_joined_voice_channel
|
||||
self._users = users
|
||||
|
||||
self.set_field("servers", self.resolve_servers)
|
||||
self.set_field("server_count", self.resolve_server_count)
|
||||
|
||||
self.set_field("known_users", self.resolve_known_users)
|
||||
self.set_field("known_user_count", self.resolve_known_users_count)
|
||||
|
||||
@FilterABC.resolve_filter_annotation
|
||||
def resolve_servers(self, *_, filter: ServerFilter = None):
|
||||
if filter is not None:
|
||||
return filter.filter(self._servers.get_servers())
|
||||
else:
|
||||
return self._servers.get_servers()
|
||||
|
||||
def resolve_server_count(self, *_):
|
||||
return self._servers.get_servers().count()
|
||||
|
||||
def resolve_known_users(self, *_):
|
||||
return self._known_users.get_users()
|
||||
|
||||
def resolve_known_users_count(self, *_):
|
||||
return self._known_users.get_users().count()
|
||||
self._add_collection("auto_role", lambda *_: self._auto_roles.get_auto_roles(), AutoRoleFilter)
|
||||
self._add_collection("auto_role_rule", lambda *_: self._auto_roles.get_auto_role_rules(), AutoRoleRuleFilter)
|
||||
self._add_collection("client", lambda *_: self._clients.get_clients())
|
||||
self._add_collection("known_user", lambda *_: self._known_users.get_users())
|
||||
self._add_collection("level", lambda *_: self._levels.get_levels(), LevelFilter)
|
||||
self._add_collection("server", lambda *_: self._servers.get_servers(), ServerFilter)
|
||||
self._add_collection("user_joined_server", lambda *_: self._user_joined_servers.get_user_joined_servers())
|
||||
self._add_collection(
|
||||
"user_joined_voice_channel", lambda *_: self._user_joined_voice_channels.get_user_joined_voice_channels()
|
||||
)
|
||||
self._add_collection("user", lambda *_: self._users.get_users(), UserFilter)
|
||||
|
Loading…
Reference in New Issue
Block a user