Compare commits
11 Commits
ed83826234
...
95b9eea236
Author | SHA1 | Date | |
---|---|---|---|
95b9eea236 | |||
b95a951a1b | |||
df42acec26 | |||
44204f5b94 | |||
ce85bb332a | |||
7a836a7f59 | |||
dacb429d9b | |||
77e18027a0 | |||
b13695b018 | |||
75500076a7 | |||
5455a6b359 |
@ -6,6 +6,7 @@
|
|||||||
"bot-api": "src/bot_api/bot-api.json",
|
"bot-api": "src/bot_api/bot-api.json",
|
||||||
"bot-core": "src/bot_core/bot-core.json",
|
"bot-core": "src/bot_core/bot-core.json",
|
||||||
"bot-data": "src/bot_data/bot-data.json",
|
"bot-data": "src/bot_data/bot-data.json",
|
||||||
|
"bot-graphql": "src/bot_graphql/bot-graphql.json",
|
||||||
"auto-role": "src/modules/auto_role/auto-role.json",
|
"auto-role": "src/modules/auto_role/auto-role.json",
|
||||||
"base": "src/modules/base/base.json",
|
"base": "src/modules/base/base.json",
|
||||||
"boot-log": "src/modules/boot_log/boot-log.json",
|
"boot-log": "src/modules/boot_log/boot-log.json",
|
||||||
|
@ -28,7 +28,8 @@
|
|||||||
"Flask-SocketIO==5.3.2",
|
"Flask-SocketIO==5.3.2",
|
||||||
"eventlet==0.33.2",
|
"eventlet==0.33.2",
|
||||||
"requests-oauthlib==1.3.1",
|
"requests-oauthlib==1.3.1",
|
||||||
"icmplib==3.0.3"
|
"icmplib==3.0.3",
|
||||||
|
"ariadne==0.17.0"
|
||||||
],
|
],
|
||||||
"DevDependencies": [
|
"DevDependencies": [
|
||||||
"cpl-cli==2022.12.1.post2"
|
"cpl-cli==2022.12.1.post2"
|
||||||
@ -55,6 +56,7 @@
|
|||||||
"../bot_api/bot-api.json",
|
"../bot_api/bot-api.json",
|
||||||
"../bot_core/bot-core.json",
|
"../bot_core/bot-core.json",
|
||||||
"../bot_data/bot-data.json",
|
"../bot_data/bot-data.json",
|
||||||
|
"../bot_graphql/bot-graphql.json",
|
||||||
"../modules/auto_role/auto-role.json",
|
"../modules/auto_role/auto-role.json",
|
||||||
"../modules/base/base.json",
|
"../modules/base/base.json",
|
||||||
"../modules/boot_log/boot-log.json",
|
"../modules/boot_log/boot-log.json",
|
||||||
|
@ -4,6 +4,7 @@ from bot_api.api_module import ApiModule
|
|||||||
from bot_core.core_extension.core_extension_module import CoreExtensionModule
|
from bot_core.core_extension.core_extension_module import CoreExtensionModule
|
||||||
from bot_core.core_module import CoreModule
|
from bot_core.core_module import CoreModule
|
||||||
from bot_data.data_module import DataModule
|
from bot_data.data_module import DataModule
|
||||||
|
from bot_graphql.graphql_module import GraphQLModule
|
||||||
from modules.auto_role.auto_role_module import AutoRoleModule
|
from modules.auto_role.auto_role_module import AutoRoleModule
|
||||||
from modules.base.base_module import BaseModule
|
from modules.base.base_module import BaseModule
|
||||||
from modules.boot_log.boot_log_module import BootLogModule
|
from modules.boot_log.boot_log_module import BootLogModule
|
||||||
@ -23,6 +24,7 @@ class ModuleList:
|
|||||||
[
|
[
|
||||||
CoreModule, # has to be first!
|
CoreModule, # has to be first!
|
||||||
DataModule,
|
DataModule,
|
||||||
|
GraphQLModule,
|
||||||
PermissionModule,
|
PermissionModule,
|
||||||
DatabaseModule,
|
DatabaseModule,
|
||||||
AutoRoleModule,
|
AutoRoleModule,
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import re
|
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
import uuid
|
import uuid
|
||||||
@ -16,7 +15,6 @@ from werkzeug.exceptions import NotFound
|
|||||||
|
|
||||||
from bot_api.configuration.api_settings import ApiSettings
|
from bot_api.configuration.api_settings import ApiSettings
|
||||||
from bot_api.configuration.authentication_settings import AuthenticationSettings
|
from bot_api.configuration.authentication_settings import AuthenticationSettings
|
||||||
from bot_api.configuration.frontend_settings import FrontendSettings
|
|
||||||
from bot_api.exception.service_error_code_enum import ServiceErrorCode
|
from bot_api.exception.service_error_code_enum import ServiceErrorCode
|
||||||
from bot_api.exception.service_exception import ServiceException
|
from bot_api.exception.service_exception import ServiceException
|
||||||
from bot_api.logging.api_logger import ApiLogger
|
from bot_api.logging.api_logger import ApiLogger
|
||||||
@ -30,7 +28,6 @@ class Api(Flask):
|
|||||||
logger: ApiLogger,
|
logger: ApiLogger,
|
||||||
services: ServiceProviderABC,
|
services: ServiceProviderABC,
|
||||||
api_settings: ApiSettings,
|
api_settings: ApiSettings,
|
||||||
frontend_settings: FrontendSettings,
|
|
||||||
auth_settings: AuthenticationSettings,
|
auth_settings: AuthenticationSettings,
|
||||||
*args,
|
*args,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
@ -146,20 +143,13 @@ class Api(Flask):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self._logger.info(
|
self._logger.info(__name__, f"Starting API {self._api_settings.host}:{self._api_settings.port}")
|
||||||
__name__,
|
|
||||||
f"Starting API {self._api_settings.host}:{self._api_settings.port}",
|
|
||||||
)
|
|
||||||
self._register_routes()
|
self._register_routes()
|
||||||
self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key)
|
self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key)
|
||||||
# from waitress import serve
|
# from waitress import serve
|
||||||
# https://docs.pylonsproject.org/projects/waitress/en/stable/arguments.html
|
# https://docs.pylonsproject.org/projects/waitress/en/stable/arguments.html
|
||||||
# serve(self, host=self._apt_settings.host, port=self._apt_settings.port, threads=10, connection_limit=1000, channel_timeout=10)
|
# serve(self, host=self._apt_settings.host, port=self._apt_settings.port, threads=10, connection_limit=1000, channel_timeout=10)
|
||||||
wsgi.server(
|
wsgi.server(eventlet.listen((self._api_settings.host, self._api_settings.port)), self, log_output=False)
|
||||||
eventlet.listen((self._api_settings.host, self._api_settings.port)),
|
|
||||||
self,
|
|
||||||
log_output=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
def on_connect(self):
|
def on_connect(self):
|
||||||
self._logger.info(__name__, f"Client connected")
|
self._logger.info(__name__, f"Client connected")
|
||||||
|
@ -14,6 +14,7 @@ from bot_api.api_thread import ApiThread
|
|||||||
from bot_api.controller.auth_controller import AuthController
|
from bot_api.controller.auth_controller import AuthController
|
||||||
from bot_api.controller.auth_discord_controller import AuthDiscordController
|
from bot_api.controller.auth_discord_controller import AuthDiscordController
|
||||||
from bot_api.controller.discord.server_controller import ServerController
|
from bot_api.controller.discord.server_controller import ServerController
|
||||||
|
from bot_api.controller.grahpql_controller import GraphQLController
|
||||||
from bot_api.controller.gui_controller import GuiController
|
from bot_api.controller.gui_controller import GuiController
|
||||||
from bot_api.event.bot_api_on_ready_event import BotApiOnReadyEvent
|
from bot_api.event.bot_api_on_ready_event import BotApiOnReadyEvent
|
||||||
from bot_api.service.auth_service import AuthService
|
from bot_api.service.auth_service import AuthService
|
||||||
@ -46,6 +47,7 @@ class ApiModule(ModuleABC):
|
|||||||
services.add_transient(GuiController)
|
services.add_transient(GuiController)
|
||||||
services.add_transient(DiscordService)
|
services.add_transient(DiscordService)
|
||||||
services.add_transient(ServerController)
|
services.add_transient(ServerController)
|
||||||
|
services.add_transient(GraphQLController)
|
||||||
|
|
||||||
# cpl-discord
|
# cpl-discord
|
||||||
self._dc.add_event(DiscordEventTypesEnum.on_ready.value, BotApiOnReadyEvent)
|
self._dc.add_event(DiscordEventTypesEnum.on_ready.value, BotApiOnReadyEvent)
|
||||||
|
40
kdb-bot/src/bot_api/controller/grahpql_controller.py
Normal file
40
kdb-bot/src/bot_api/controller/grahpql_controller.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
from ariadne import graphql_sync
|
||||||
|
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
|
||||||
|
from bot_graphql.schema import Schema
|
||||||
|
|
||||||
|
|
||||||
|
class GraphQLController:
|
||||||
|
BasePath = f"/api/graphql"
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
config: ConfigurationABC,
|
||||||
|
env: ApplicationEnvironmentABC,
|
||||||
|
logger: ApiLogger,
|
||||||
|
schema: Schema,
|
||||||
|
):
|
||||||
|
self._config = config
|
||||||
|
self._env = env
|
||||||
|
self._logger = logger
|
||||||
|
self._schema = schema
|
||||||
|
|
||||||
|
@Route.get(f"{BasePath}/playground")
|
||||||
|
async def playground(self):
|
||||||
|
return PLAYGROUND_HTML, 200
|
||||||
|
|
||||||
|
@Route.post(f"{BasePath}")
|
||||||
|
async def graphql(self):
|
||||||
|
data = request.get_json()
|
||||||
|
|
||||||
|
# Note: Passing the request to the context is optional.
|
||||||
|
# In Flask, the current request is always accessible as flask.request
|
||||||
|
success, result = graphql_sync(self._schema.schema, data, context_value=request)
|
||||||
|
|
||||||
|
return jsonify(result), 200 if success else 400
|
@ -38,6 +38,8 @@ class ClientRepositoryService(ClientRepositoryABC):
|
|||||||
result[5],
|
result[5],
|
||||||
result[6],
|
result[6],
|
||||||
self._servers.get_server_by_id(result[7]),
|
self._servers.get_server_by_id(result[7]),
|
||||||
|
result[8],
|
||||||
|
result[9],
|
||||||
id=result[0],
|
id=result[0],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -55,6 +57,8 @@ class ClientRepositoryService(ClientRepositoryABC):
|
|||||||
result[5],
|
result[5],
|
||||||
result[6],
|
result[6],
|
||||||
self._servers.get_server_by_id(result[7]),
|
self._servers.get_server_by_id(result[7]),
|
||||||
|
result[8],
|
||||||
|
result[9],
|
||||||
id=result[0],
|
id=result[0],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -72,6 +76,8 @@ class ClientRepositoryService(ClientRepositoryABC):
|
|||||||
result[5],
|
result[5],
|
||||||
result[6],
|
result[6],
|
||||||
self._servers.get_server_by_id(result[7]),
|
self._servers.get_server_by_id(result[7]),
|
||||||
|
result[8],
|
||||||
|
result[9],
|
||||||
id=result[0],
|
id=result[0],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -94,6 +100,8 @@ class ClientRepositoryService(ClientRepositoryABC):
|
|||||||
result[5],
|
result[5],
|
||||||
result[6],
|
result[6],
|
||||||
self._servers.get_server_by_id(result[7]),
|
self._servers.get_server_by_id(result[7]),
|
||||||
|
result[8],
|
||||||
|
result[9],
|
||||||
id=result[0],
|
id=result[0],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -116,6 +124,8 @@ class ClientRepositoryService(ClientRepositoryABC):
|
|||||||
result[5],
|
result[5],
|
||||||
result[6],
|
result[6],
|
||||||
self._servers.get_server_by_id(result[7]),
|
self._servers.get_server_by_id(result[7]),
|
||||||
|
result[8],
|
||||||
|
result[9],
|
||||||
id=result[0],
|
id=result[0],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -138,6 +148,8 @@ class ClientRepositoryService(ClientRepositoryABC):
|
|||||||
result[5],
|
result[5],
|
||||||
result[6],
|
result[6],
|
||||||
self._servers.get_server_by_id(result[7]),
|
self._servers.get_server_by_id(result[7]),
|
||||||
|
result[8],
|
||||||
|
result[9],
|
||||||
id=result[0],
|
id=result[0],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ class ServerRepositoryService(ServerRepositoryABC):
|
|||||||
self._logger.trace(__name__, f"Send SQL command: {Server.get_select_all_string()}")
|
self._logger.trace(__name__, f"Send SQL command: {Server.get_select_all_string()}")
|
||||||
results = self._context.select(Server.get_select_all_string())
|
results = self._context.select(Server.get_select_all_string())
|
||||||
for result in results:
|
for result in results:
|
||||||
servers.append(Server(result[1], id=result[0]))
|
servers.append(Server(result[1], result[2], result[3], id=result[0]))
|
||||||
|
|
||||||
return servers
|
return servers
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ class ServerRepositoryService(ServerRepositoryABC):
|
|||||||
def get_server_by_id(self, server_id: int) -> Server:
|
def get_server_by_id(self, server_id: int) -> Server:
|
||||||
self._logger.trace(__name__, f"Send SQL command: {Server.get_select_by_id_string(server_id)}")
|
self._logger.trace(__name__, f"Send SQL command: {Server.get_select_by_id_string(server_id)}")
|
||||||
result = self._context.select(Server.get_select_by_id_string(server_id))[0]
|
result = self._context.select(Server.get_select_by_id_string(server_id))[0]
|
||||||
return Server(result[1], id=result[0])
|
return Server(result[1], result[2], result[3], id=result[0])
|
||||||
|
|
||||||
def get_server_by_discord_id(self, discord_id: int) -> Server:
|
def get_server_by_discord_id(self, discord_id: int) -> Server:
|
||||||
self._logger.trace(
|
self._logger.trace(
|
||||||
@ -62,7 +62,7 @@ class ServerRepositoryService(ServerRepositoryABC):
|
|||||||
f"Send SQL command: {Server.get_select_by_discord_id_string(discord_id)}",
|
f"Send SQL command: {Server.get_select_by_discord_id_string(discord_id)}",
|
||||||
)
|
)
|
||||||
result = self._context.select(Server.get_select_by_discord_id_string(discord_id))[0]
|
result = self._context.select(Server.get_select_by_discord_id_string(discord_id))[0]
|
||||||
return Server(result[1], id=result[0])
|
return Server(result[1], result[2], result[3], id=result[0])
|
||||||
|
|
||||||
def find_server_by_discord_id(self, discord_id: int) -> Optional[Server]:
|
def find_server_by_discord_id(self, discord_id: int) -> Optional[Server]:
|
||||||
self._logger.trace(
|
self._logger.trace(
|
||||||
|
1
kdb-bot/src/bot_graphql/__init__.py
Normal file
1
kdb-bot/src/bot_graphql/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
# imports
|
0
kdb-bot/src/bot_graphql/abc/__init__.py
Normal file
0
kdb-bot/src/bot_graphql/abc/__init__.py
Normal file
19
kdb-bot/src/bot_graphql/abc/data_query_abc.py
Normal file
19
kdb-bot/src/bot_graphql/abc/data_query_abc.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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
|
67
kdb-bot/src/bot_graphql/abc/filter_abc.py
Normal file
67
kdb-bot/src/bot_graphql/abc/filter_abc.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import functools
|
||||||
|
from abc import ABC
|
||||||
|
from inspect import signature, Parameter
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from cpl_query.extension import List
|
||||||
|
|
||||||
|
|
||||||
|
class FilterABC(ABC):
|
||||||
|
def __init__(self):
|
||||||
|
ABC.__init__(self)
|
||||||
|
|
||||||
|
self._page_index = None
|
||||||
|
self._page_size = None
|
||||||
|
self._sort_direction = None
|
||||||
|
self._sort_column = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def page_index(self) -> Optional[int]:
|
||||||
|
return self._page_index
|
||||||
|
|
||||||
|
@property
|
||||||
|
def page_size(self) -> Optional[int]:
|
||||||
|
return self._page_size
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sort_direction(self) -> Optional[str]:
|
||||||
|
return self._sort_direction
|
||||||
|
|
||||||
|
@property
|
||||||
|
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.name == "cls" 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.resolve_filter_annotation)
|
||||||
|
|
||||||
|
@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
|
5
kdb-bot/src/bot_graphql/abc/query_abc.py
Normal file
5
kdb-bot/src/bot_graphql/abc/query_abc.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from ariadne import ObjectType
|
||||||
|
|
||||||
|
|
||||||
|
class QueryABC(ObjectType):
|
||||||
|
__abstract__ = True
|
44
kdb-bot/src/bot_graphql/bot-graphql.json
Normal file
44
kdb-bot/src/bot_graphql/bot-graphql.json
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"ProjectSettings": {
|
||||||
|
"Name": "bot-data",
|
||||||
|
"Version": {
|
||||||
|
"Major": "0",
|
||||||
|
"Minor": "1",
|
||||||
|
"Micro": "0"
|
||||||
|
},
|
||||||
|
"Author": "Sven Heidemann",
|
||||||
|
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
||||||
|
"Description": "Keksdose bot - graphql",
|
||||||
|
"LongDescription": "Discord bot for the Keksdose discord Server - graphql package",
|
||||||
|
"URL": "https://www.sh-edraft.de",
|
||||||
|
"CopyrightDate": "2023",
|
||||||
|
"CopyrightName": "sh-edraft.de",
|
||||||
|
"LicenseName": "MIT",
|
||||||
|
"LicenseDescription": "MIT, see LICENSE for more details.",
|
||||||
|
"Dependencies": [
|
||||||
|
"cpl-core>=2022.12.1"
|
||||||
|
],
|
||||||
|
"DevDependencies": [
|
||||||
|
"cpl-cli>=2022.12.1"
|
||||||
|
],
|
||||||
|
"PythonVersion": ">=3.10.4",
|
||||||
|
"PythonPath": {},
|
||||||
|
"Classifiers": []
|
||||||
|
},
|
||||||
|
"BuildSettings": {
|
||||||
|
"ProjectType": "library",
|
||||||
|
"SourcePath": "",
|
||||||
|
"OutputPath": "../../dist",
|
||||||
|
"Main": "",
|
||||||
|
"EntryPoint": "",
|
||||||
|
"IncludePackageData": false,
|
||||||
|
"Included": [],
|
||||||
|
"Excluded": [
|
||||||
|
"*/__pycache__",
|
||||||
|
"*/logs",
|
||||||
|
"*/tests"
|
||||||
|
],
|
||||||
|
"PackageData": {},
|
||||||
|
"ProjectReferences": []
|
||||||
|
}
|
||||||
|
}
|
0
kdb-bot/src/bot_graphql/filter/__init__.py
Normal file
0
kdb-bot/src/bot_graphql/filter/__init__.py
Normal file
36
kdb-bot/src/bot_graphql/filter/level_filter.py
Normal file
36
kdb-bot/src/bot_graphql/filter/level_filter.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
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
|
40
kdb-bot/src/bot_graphql/filter/server_filter.py
Normal file
40
kdb-bot/src/bot_graphql/filter/server_filter.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
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 = int(values["id"])
|
||||||
|
|
||||||
|
@ServiceProviderABC.inject
|
||||||
|
def filter(self, query: List[Server], bot: DiscordBotServiceABC) -> 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)
|
||||||
|
|
||||||
|
return self.skip_and_take(query)
|
36
kdb-bot/src/bot_graphql/graphql_module.py
Normal file
36
kdb-bot/src/bot_graphql/graphql_module.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
from cpl_core.configuration import ConfigurationABC
|
||||||
|
from cpl_core.dependency_injection import ServiceCollectionABC
|
||||||
|
from cpl_core.environment import ApplicationEnvironmentABC
|
||||||
|
from cpl_discord.service.discord_collection_abc import DiscordCollectionABC
|
||||||
|
|
||||||
|
from bot_core.abc.module_abc import ModuleABC
|
||||||
|
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.mutation import Mutation
|
||||||
|
from bot_graphql.mutations.level_mutation import LevelMutation
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
class GraphQLModule(ModuleABC):
|
||||||
|
def __init__(self, dc: DiscordCollectionABC):
|
||||||
|
ModuleABC.__init__(self, dc, FeatureFlagsEnum.data_module)
|
||||||
|
|
||||||
|
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||||
|
|
||||||
|
services.add_singleton(Schema)
|
||||||
|
services.add_singleton(GraphQLService)
|
||||||
|
services.add_singleton(Query)
|
||||||
|
services.add_singleton(Mutation)
|
||||||
|
services.add_transient(QueryABC, ServerQuery)
|
||||||
|
services.add_transient(QueryABC, LevelQuery)
|
||||||
|
services.add_transient(QueryABC, LevelMutation)
|
||||||
|
|
||||||
|
services.add_transient(SeederService)
|
6
kdb-bot/src/bot_graphql/graphql_service.py
Normal file
6
kdb-bot/src/bot_graphql/graphql_service.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from bot_graphql.abc.query_abc import QueryABC
|
||||||
|
|
||||||
|
|
||||||
|
class GraphQLService:
|
||||||
|
def __init__(self, queries: list[QueryABC]):
|
||||||
|
self._queries = queries
|
123
kdb-bot/src/bot_graphql/model.gql
Normal file
123
kdb-bot/src/bot_graphql/model.gql
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
interface TableQuery {
|
||||||
|
created_at: String
|
||||||
|
modified_at: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type Mutation {
|
||||||
|
level: LevelMutation
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
servers(filter: ServerFilter): [Server]
|
||||||
|
server_count: Int
|
||||||
|
known_users: [User]
|
||||||
|
}
|
||||||
|
|
||||||
|
input ServerFilter {
|
||||||
|
id: ID
|
||||||
|
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]
|
||||||
|
levels: [Level]
|
||||||
|
|
||||||
|
created_at: String
|
||||||
|
modified_at: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type Client implements TableQuery {
|
||||||
|
id: ID
|
||||||
|
discord_id: String
|
||||||
|
sent_message_count: Int
|
||||||
|
received_message_count: Int
|
||||||
|
deleted_message_count: Int
|
||||||
|
received_command_count: Int
|
||||||
|
moved_users_count: Int
|
||||||
|
|
||||||
|
server: Server
|
||||||
|
|
||||||
|
created_at: String
|
||||||
|
modified_at: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type User implements TableQuery {
|
||||||
|
id: ID
|
||||||
|
discord_id: String
|
||||||
|
name: String
|
||||||
|
xp: Int
|
||||||
|
ontime: Int
|
||||||
|
level: Level
|
||||||
|
|
||||||
|
joined_servers: [UserJoinedServer]
|
||||||
|
joined_voice_channel: [UserJoinedVoiceChannel]
|
||||||
|
|
||||||
|
server: Server
|
||||||
|
|
||||||
|
created_at: String
|
||||||
|
modified_at: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserJoinedServer implements TableQuery {
|
||||||
|
id: ID
|
||||||
|
user: User
|
||||||
|
server: Server
|
||||||
|
joined_on: String
|
||||||
|
leaved_on: String
|
||||||
|
|
||||||
|
created_at: String
|
||||||
|
modified_at: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserJoinedVoiceChannel implements TableQuery {
|
||||||
|
id: ID
|
||||||
|
channel_id: String
|
||||||
|
user: User
|
||||||
|
joined_on: String
|
||||||
|
leaved_on: String
|
||||||
|
|
||||||
|
created_at: String
|
||||||
|
modified_at: String
|
||||||
|
}
|
||||||
|
|
||||||
|
input LevelFilter {
|
||||||
|
id: ID
|
||||||
|
name: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type Level implements TableQuery {
|
||||||
|
id: ID
|
||||||
|
name: String
|
||||||
|
color: String
|
||||||
|
min_xp: Int
|
||||||
|
permissions: String
|
||||||
|
|
||||||
|
server: Server
|
||||||
|
|
||||||
|
created_at: String
|
||||||
|
modified_at: String
|
||||||
|
}
|
||||||
|
|
||||||
|
input LevelInput {
|
||||||
|
name: String!
|
||||||
|
color: String!
|
||||||
|
min_xp: Int!
|
||||||
|
permissions: String!
|
||||||
|
server_id: ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
type LevelMutation {
|
||||||
|
create_level(input: LevelInput!): Level
|
||||||
|
update_level(input: LevelInput!): Level
|
||||||
|
delete_level(id: ID): Level
|
||||||
|
}
|
14
kdb-bot/src/bot_graphql/mutation.py
Normal file
14
kdb-bot/src/bot_graphql/mutation.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from ariadne import MutationType
|
||||||
|
|
||||||
|
from bot_graphql.mutations.level_mutation import LevelMutation
|
||||||
|
|
||||||
|
|
||||||
|
class Mutation(MutationType):
|
||||||
|
def __init__(self, level_mutation: LevelMutation):
|
||||||
|
MutationType.__init__(self)
|
||||||
|
|
||||||
|
self._level_mutation = level_mutation
|
||||||
|
self.set_field("level", self.resolve_level)
|
||||||
|
|
||||||
|
def resolve_level(self, *_):
|
||||||
|
return self._level_mutation
|
0
kdb-bot/src/bot_graphql/mutations/__init__.py
Normal file
0
kdb-bot/src/bot_graphql/mutations/__init__.py
Normal file
32
kdb-bot/src/bot_graphql/mutations/level_mutation.py
Normal file
32
kdb-bot/src/bot_graphql/mutations/level_mutation.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from bot_data.abc.level_repository_abc import LevelRepositoryABC
|
||||||
|
from bot_data.abc.server_repository_abc import ServerRepositoryABC
|
||||||
|
from bot_data.model.level import Level
|
||||||
|
from bot_graphql.abc.query_abc import QueryABC
|
||||||
|
|
||||||
|
|
||||||
|
class LevelMutation(QueryABC):
|
||||||
|
def __init__(self, servers: ServerRepositoryABC, levels: LevelRepositoryABC):
|
||||||
|
QueryABC.__init__(self, "LevelMutation")
|
||||||
|
|
||||||
|
self._servers = servers
|
||||||
|
self._levels = levels
|
||||||
|
|
||||||
|
self.set_field("create_level", self.resolve_create_level)
|
||||||
|
self.set_field("update_level", self.resolve_create_level)
|
||||||
|
self.set_field("delete_level", self.resolve_create_level)
|
||||||
|
|
||||||
|
def resolve_create_level(self, *_, input: dict):
|
||||||
|
level = Level(
|
||||||
|
input["name"],
|
||||||
|
input["color"],
|
||||||
|
int(input["min_xp"]),
|
||||||
|
int(input["permissions"]),
|
||||||
|
self._servers.get_server_by_id(input["server_id"]),
|
||||||
|
)
|
||||||
|
return level
|
||||||
|
|
||||||
|
def resolve_update_level(self, *_, input):
|
||||||
|
return self._levels.get_level_by_id(input.id)
|
||||||
|
|
||||||
|
def resolve_delete_level(self, *_, id: int):
|
||||||
|
return self._levels.get_level_by_id(id)
|
0
kdb-bot/src/bot_graphql/queries/__init__.py
Normal file
0
kdb-bot/src/bot_graphql/queries/__init__.py
Normal file
38
kdb-bot/src/bot_graphql/queries/level_query.py
Normal file
38
kdb-bot/src/bot_graphql/queries/level_query.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
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
|
43
kdb-bot/src/bot_graphql/queries/server_query.py
Normal file
43
kdb-bot/src/bot_graphql/queries/server_query.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
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,
|
||||||
|
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, *_):
|
||||||
|
return server.server_id
|
||||||
|
|
||||||
|
@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
|
||||||
|
|
||||||
|
@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)
|
24
kdb-bot/src/bot_graphql/query.py
Normal file
24
kdb-bot/src/bot_graphql/query.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
from ariadne import QueryType
|
||||||
|
|
||||||
|
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):
|
||||||
|
def __init__(self, servers: ServerRepositoryService):
|
||||||
|
QueryType.__init__(self)
|
||||||
|
self._servers = servers
|
||||||
|
|
||||||
|
self.set_field("servers", self.resolve_servers)
|
||||||
|
self.set_field("server_count", self.resolve_server_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()
|
18
kdb-bot/src/bot_graphql/schema.py
Normal file
18
kdb-bot/src/bot_graphql/schema.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from ariadne import make_executable_schema, load_schema_from_path
|
||||||
|
from graphql import GraphQLSchema
|
||||||
|
|
||||||
|
from bot_graphql.abc.query_abc import QueryABC
|
||||||
|
from bot_graphql.mutation import Mutation
|
||||||
|
from bot_graphql.query import Query
|
||||||
|
|
||||||
|
|
||||||
|
class Schema:
|
||||||
|
def __init__(self, query: Query, mutation: Mutation, queries: list[QueryABC]):
|
||||||
|
type_defs = load_schema_from_path(os.path.join(os.path.dirname(os.path.realpath(__file__)), "model.gql"))
|
||||||
|
self._schema = make_executable_schema(type_defs, query, mutation, *queries)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def schema(self) -> GraphQLSchema:
|
||||||
|
return self._schema
|
Loading…
Reference in New Issue
Block a user