GraphQL Part1 (gql endpoint only) #162 #192

Merged
edraft merged 38 commits from #162 into 1.0.0 2023-02-11 10:30:42 +01:00
8 changed files with 193 additions and 18 deletions
Showing only changes of commit 7a836a7f59 - Show all commits

View File

@ -29,8 +29,7 @@
"eventlet==0.33.2",
"requests-oauthlib==1.3.1",
"icmplib==3.0.3",
"ariadne==0.17.0",
"ariadne-graphql-modules==0.7.0"
"ariadne==0.17.0"
],
"DevDependencies": [
"cpl-cli==2022.12.0"

View File

@ -3,6 +3,7 @@ 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

View File

@ -0,0 +1,20 @@
from cpl_core.database import TableABC
from bot_graphql.abc.query_abc import QueryABC
class DataQueryABC(QueryABC):
def __init__(self, name: str):
QueryABC.__init__(self, name)
self.set_field('created_at', self.resolve_created_at)
self.set_field('modified_at', self.resolve_modified_at)
@staticmethod
def resolve_created_at(entry: TableABC, *_):
return entry.created_at
@staticmethod
def resolve_modified_at(entry: TableABC, *_):
return entry.modified_at

View File

@ -0,0 +1,57 @@
import functools
from abc import ABC
from inspect import signature, Parameter
class FilterABC(ABC):
def __init__(self):
ABC.__init__(self)
self._page_index = 0
self._page_size = 10
self._sort_direction = ''
self._sort_column = ''
@property
def page_index(self) -> int:
return self._page_index
@property
def page_size(self) -> int:
return self._page_size
@property
def sort_direction(self) -> str:
return self._sort_direction
@property
def sort_column(self) -> str:
return self._sort_column
@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:
continue
if issubclass(parameter.annotation, FilterABC):
filter = parameter.annotation()
filter.from_dict(values)
return filter
@classmethod
def resolve_filter_annotation(cls, f=None):
if f is None:
return functools.partial(cls.filter)
@functools.wraps(f)
def decorator(*args, **kwargs):
if 'filter' in kwargs:
kwargs['filter'] = cls.get_filter(f, kwargs['filter'])
return f(*args, **kwargs)
return decorator

View File

@ -1,2 +1,43 @@
class ServerFilter:
pass
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.server import Server
from bot_graphql.abc.filter_abc import FilterABC
class ServerFilter(FilterABC):
def __init__(self):
FilterABC.__init__(self)
self._id = None
self._discord_id = None
self._name = None
def from_dict(self, values: dict):
if 'id' in values:
self._id = 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)
if self._discord_id is not None:
query = query.where(lambda x: x.discord_server_id == self._discord_id)
if self._name is not None:
def where_guild(x: Guild):
guild = bot.get_guild(x.discord_server_id)
return guild is not None and (self._name.lower() == guild.name.lower() or self._name.lower() in guild.name.lower())
query = query.where(where_guild)
skip = self.page_size * self.page_index
result = query.skip(skip).take(self.page_size)
return result

View File

@ -1,17 +1,38 @@
type Query {
servers: [Server]
servers(filter: ServerFilter): [Server]
server_count: Int
known_users: [User]
}
type Server {
interface TableQuery {
created_at: String
modified_at: String
}
input ServerFilter {
id: Int
discord_id: String
name: String
page_index: Int
page_size: Int
sort_direction: String
sort_column: String
}
type Server implements TableQuery {
id: ID
discord_id: String
name: String
clients: [Client]
members: [User]
level: [Level]
created_at: String
modified_at: String
}
type Client {
type Client implements TableQuery {
id: ID
discord_id: String
sent_message_count: Int
@ -21,9 +42,12 @@ type Client {
moved_users_count: Int
server: Server
created_at: String
modified_at: String
}
type User {
type User implements TableQuery {
id: ID
discord_id: String
name: String
@ -35,25 +59,34 @@ type User {
joined_voice_channel: [UserJoinedVoiceChannel]
server: Server
created_at: String
modified_at: String
}
type UserJoinedServer {
type UserJoinedServer implements TableQuery {
id: ID
user: User
server: Server
joined_on: String
leaved_on: String
created_at: String
modified_at: String
}
type UserJoinedVoiceChannel {
type UserJoinedVoiceChannel implements TableQuery {
id: ID
channel_id: String
user: User
joined_on: String
leaved_on: String
created_at: String
modified_at: String
}
type Level {
type Level implements TableQuery {
id: ID
name: String
color: String
@ -61,4 +94,7 @@ type Level {
permissions: String
server: Server
created_at: String
modified_at: String
}

View File

@ -1,14 +1,22 @@
from bot_graphql.abc.query_abc import QueryABC
from cpl_discord.service import DiscordBotServiceABC
from bot_data.model.server import Server
from bot_graphql.abc.data_query_abc import DataQueryABC
class ServerQuery(QueryABC):
class ServerQuery(DataQueryABC):
def __init__(self):
QueryABC.__init__(self, 'Server')
def __init__(
self,
bot: DiscordBotServiceABC
):
DataQueryABC.__init__(self, 'Server')
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)
@staticmethod
def resolve_id(server: Server, *_):
@ -17,3 +25,7 @@ class ServerQuery(QueryABC):
@staticmethod
def resolve_discord_id(server: Server, *_):
return server.discord_server_id
def resolve_name(self, server: Server, *_):
guild = self._bot.get_guild(server.discord_server_id)
return None if guild is None else guild.name

View File

@ -1,7 +1,8 @@
from ariadne import QueryType
from bot_graphql.filter.server_filter import ServerFilter
from bot_data.service.server_repository_service import ServerRepositoryService
from bot_graphql.abc.filter_abc import FilterABC
from bot_graphql.filter.server_filter import ServerFilter
class Query(QueryType):
@ -14,6 +15,14 @@ class Query(QueryType):
self._servers = servers
self.set_field('servers', self.resolve_servers)
self.set_field('server_count', self.resolve_server_count)
def resolve_servers(self, filter: ServerFilter, *_):
return self._servers.get_servers()
@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()