1.0.0 #253
| @@ -6,6 +6,7 @@ | ||||
|       "bot-api": "src/bot_api/bot-api.json", | ||||
|       "bot-core": "src/bot_core/bot-core.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", | ||||
|       "base": "src/modules/base/base.json", | ||||
|       "boot-log": "src/modules/boot_log/boot-log.json", | ||||
|   | ||||
| @@ -28,7 +28,8 @@ | ||||
|       "Flask-SocketIO==5.3.2", | ||||
|       "eventlet==0.33.2", | ||||
|       "requests-oauthlib==1.3.1", | ||||
|       "icmplib==3.0.3" | ||||
|       "icmplib==3.0.3", | ||||
|       "ariadne==0.17.0" | ||||
|     ], | ||||
|     "DevDependencies": [ | ||||
|       "cpl-cli==2022.12.1.post2" | ||||
| @@ -55,6 +56,7 @@ | ||||
|       "../bot_api/bot-api.json", | ||||
|       "../bot_core/bot-core.json", | ||||
|       "../bot_data/bot-data.json", | ||||
|       "../bot_graphql/bot-graphql.json", | ||||
|       "../modules/auto_role/auto-role.json", | ||||
|       "../modules/base/base.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_module import CoreModule | ||||
| 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.base.base_module import BaseModule | ||||
| from modules.boot_log.boot_log_module import BootLogModule | ||||
| @@ -15,6 +16,7 @@ from modules.technician.technician_module import TechnicianModule | ||||
|  | ||||
|  | ||||
| class ModuleList: | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_modules(): | ||||
|         # core modules (modules out of modules folder) should be loaded first! | ||||
| @@ -23,6 +25,7 @@ class ModuleList: | ||||
|             [ | ||||
|                 CoreModule,  # has to be first! | ||||
|                 DataModule, | ||||
|                 GraphQLModule, | ||||
|                 PermissionModule, | ||||
|                 DatabaseModule, | ||||
|                 AutoRoleModule, | ||||
|   | ||||
| @@ -22,21 +22,23 @@ from bot_api.exception.service_exception import ServiceException | ||||
| from bot_api.logging.api_logger import ApiLogger | ||||
| from bot_api.model.error_dto import ErrorDTO | ||||
| from bot_api.route.route import Route | ||||
| from bot_graphql.graphql_service import GraphQLService | ||||
|  | ||||
|  | ||||
| class Api(Flask): | ||||
|  | ||||
|     def __init__( | ||||
|         self, | ||||
|         logger: ApiLogger, | ||||
|         services: ServiceProviderABC, | ||||
|         api_settings: ApiSettings, | ||||
|         frontend_settings: FrontendSettings, | ||||
|         auth_settings: AuthenticationSettings, | ||||
|         *args, | ||||
|         **kwargs, | ||||
|             self, | ||||
|             logger: ApiLogger, | ||||
|             services: ServiceProviderABC, | ||||
|             api_settings: ApiSettings, | ||||
|             frontend_settings: FrontendSettings, | ||||
|             auth_settings: AuthenticationSettings, | ||||
|             graphql: GraphQLService, | ||||
|             *args, **kwargs | ||||
|     ): | ||||
|         if not args: | ||||
|             kwargs.setdefault("import_name", __name__) | ||||
|             kwargs.setdefault('import_name', __name__) | ||||
|  | ||||
|         Flask.__init__(self, *args, **kwargs) | ||||
|  | ||||
| @@ -56,21 +58,17 @@ class Api(Flask): | ||||
|         self.register_error_handler(exc_class, self.handle_exception) | ||||
|  | ||||
|         # websockets | ||||
|         self._socketio = SocketIO(self, cors_allowed_origins="*", path="/api/socket.io") | ||||
|         self._socketio.on_event("connect", self.on_connect) | ||||
|         self._socketio.on_event("disconnect", self.on_disconnect) | ||||
|         self._socketio = SocketIO(self, cors_allowed_origins='*', path='/api/socket.io') | ||||
|         self._socketio.on_event('connect', self.on_connect) | ||||
|         self._socketio.on_event('disconnect', self.on_disconnect) | ||||
|  | ||||
|         self._requests = {} | ||||
|  | ||||
|     @staticmethod | ||||
|     def _get_methods_from_registered_route() -> Union[list[str], str]: | ||||
|         methods = ["Unknown"] | ||||
|         if ( | ||||
|             request.path in Route.registered_routes | ||||
|             and len(Route.registered_routes[request.path]) >= 1 | ||||
|             and "methods" in Route.registered_routes[request.path][1] | ||||
|         ): | ||||
|             methods = Route.registered_routes[request.path][1]["methods"] | ||||
|         methods = ['Unknown'] | ||||
|         if request.path in Route.registered_routes and len(Route.registered_routes[request.path]) >= 1 and 'methods' in Route.registered_routes[request.path][1]: | ||||
|             methods = Route.registered_routes[request.path][1]['methods'] | ||||
|  | ||||
|         if len(methods) == 1: | ||||
|             return methods[0] | ||||
| @@ -81,7 +79,7 @@ class Api(Flask): | ||||
|             route = f[0] | ||||
|             kwargs = f[1] | ||||
|             cls = None | ||||
|             qual_name_split = route.__qualname__.split(".") | ||||
|             qual_name_split = route.__qualname__.split('.') | ||||
|             if len(qual_name_split) > 0: | ||||
|                 cls_type = vars(sys.modules[route.__module__])[qual_name_split[0]] | ||||
|                 cls = self._services.get_service(cls_type) | ||||
| @@ -91,7 +89,7 @@ class Api(Flask): | ||||
|             self.route(path, **kwargs)(partial_f) | ||||
|  | ||||
|     def handle_exception(self, e: Exception): | ||||
|         self._logger.error(__name__, f"Caught error", e) | ||||
|         self._logger.error(__name__, f'Caught error', e) | ||||
|  | ||||
|         if isinstance(e, ServiceException): | ||||
|             ex: ServiceException = e | ||||
| @@ -104,7 +102,7 @@ class Api(Flask): | ||||
|             return jsonify(error.to_dict()), 404 | ||||
|         else: | ||||
|             tracking_id = uuid.uuid4() | ||||
|             user_message = f"Tracking Id: {tracking_id}" | ||||
|             user_message = f'Tracking Id: {tracking_id}' | ||||
|             self._logger.error(__name__, user_message, e) | ||||
|             error = ErrorDTO(None, user_message) | ||||
|             return jsonify(error.to_dict()), 400 | ||||
| @@ -114,42 +112,34 @@ class Api(Flask): | ||||
|         self._requests[request] = request_id | ||||
|         method = request.access_control_request_method | ||||
|  | ||||
|         self._logger.info( | ||||
|             __name__, | ||||
|             f"Received {request_id} @ {self._get_methods_from_registered_route() if method is None else method} {request.url} from {request.remote_addr}", | ||||
|         ) | ||||
|         self._logger.info(__name__, f'Received {request_id} @ {self._get_methods_from_registered_route() if method is None else method} {request.url} from {request.remote_addr}') | ||||
|  | ||||
|         headers = str(request.headers).replace("\n", "\n\t\t") | ||||
|         headers = str(request.headers).replace('\n', '\n\t\t') | ||||
|         data = request.get_data() | ||||
|         data = "" if len(data) == 0 else str(data.decode(encoding="utf-8")) | ||||
|         data = '' if len(data) == 0 else str(data.decode(encoding="utf-8")) | ||||
|  | ||||
|         text = textwrap.dedent( | ||||
|             f"Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tUser-Agent: {request.user_agent.string}\n\tBody: {data}" | ||||
|         ) | ||||
|         text = textwrap.dedent(f'Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tUser-Agent: {request.user_agent.string}\n\tBody: {data}') | ||||
|         self._logger.trace(__name__, text) | ||||
|  | ||||
|     def after_request_hook(self, response: Response): | ||||
|         method = request.access_control_request_method | ||||
|         request_id = f"{self._get_methods_from_registered_route() if method is None else method} {request.url} from {request.remote_addr}" | ||||
|         request_id = f'{self._get_methods_from_registered_route() if method is None else method} {request.url} from {request.remote_addr}' | ||||
|         if request in self._requests: | ||||
|             request_id = self._requests[request] | ||||
|  | ||||
|         self._logger.info(__name__, f"Answered {request_id}") | ||||
|         self._logger.info(__name__, f'Answered {request_id}') | ||||
|  | ||||
|         headers = str(request.headers).replace("\n", "\n\t\t") | ||||
|         headers = str(request.headers).replace('\n', '\n\t\t') | ||||
|         data = request.get_data() | ||||
|         data = "" if len(data) == 0 else str(data.decode(encoding="utf-8")) | ||||
|         data = '' if len(data) == 0 else str(data.decode(encoding="utf-8")) | ||||
|  | ||||
|         text = textwrap.dedent(f"Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tResponse: {data}") | ||||
|         text = textwrap.dedent(f'Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tResponse: {data}') | ||||
|         self._logger.trace(__name__, text) | ||||
|  | ||||
|         return response | ||||
|  | ||||
|     def start(self): | ||||
|         self._logger.info( | ||||
|             __name__, | ||||
|             f"Starting API {self._api_settings.host}:{self._api_settings.port}", | ||||
|         ) | ||||
|         self._logger.info(__name__, f'Starting API {self._api_settings.host}:{self._api_settings.port}') | ||||
|         self._register_routes() | ||||
|         self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key) | ||||
|         # from waitress import serve | ||||
| @@ -158,11 +148,11 @@ class Api(Flask): | ||||
|         wsgi.server( | ||||
|             eventlet.listen((self._api_settings.host, self._api_settings.port)), | ||||
|             self, | ||||
|             log_output=False, | ||||
|             log_output=False | ||||
|         ) | ||||
|  | ||||
|     def on_connect(self): | ||||
|         self._logger.info(__name__, f"Client connected") | ||||
|         self._logger.info(__name__, f'Client connected') | ||||
|  | ||||
|     def on_disconnect(self): | ||||
|         self._logger.info(__name__, f"Client disconnected") | ||||
|         self._logger.info(__name__, f'Client disconnected') | ||||
|   | ||||
| @@ -14,6 +14,7 @@ from bot_api.api_thread import ApiThread | ||||
| from bot_api.controller.auth_controller import AuthController | ||||
| from bot_api.controller.auth_discord_controller import AuthDiscordController | ||||
| 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.event.bot_api_on_ready_event import BotApiOnReadyEvent | ||||
| from bot_api.service.auth_service import AuthService | ||||
| @@ -46,6 +47,7 @@ class ApiModule(ModuleABC): | ||||
|         services.add_transient(GuiController) | ||||
|         services.add_transient(DiscordService) | ||||
|         services.add_transient(ServerController) | ||||
|         services.add_transient(GraphQLController) | ||||
|  | ||||
|         # cpl-discord | ||||
|         self._dc.add_event(DiscordEventTypesEnum.on_ready.value, BotApiOnReadyEvent) | ||||
|   | ||||
							
								
								
									
										44
									
								
								kdb-bot/src/bot_api/controller/grahpql_controller.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								kdb-bot/src/bot_api/controller/grahpql_controller.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| 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 | ||||
| @@ -28,19 +28,19 @@ class ClientRepositoryService(ClientRepositoryABC): | ||||
|         self._logger.trace(__name__, f"Send SQL command: {Client.get_select_all_string()}") | ||||
|         results = self._context.select(Client.get_select_all_string()) | ||||
|         for result in results: | ||||
|             self._logger.trace(__name__, f"Get client with id {result[0]}") | ||||
|             clients.append( | ||||
|                 Client( | ||||
|                     result[1], | ||||
|                     result[2], | ||||
|                     result[3], | ||||
|                     result[4], | ||||
|                     result[5], | ||||
|                     result[6], | ||||
|                     self._servers.get_server_by_id(result[7]), | ||||
|                     id=result[0], | ||||
|                 ) | ||||
|             ) | ||||
|             self._logger.trace(__name__, f'Get client with id {result[0]}') | ||||
|             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 | ||||
|  | ||||
| @@ -55,7 +55,9 @@ class ClientRepositoryService(ClientRepositoryABC): | ||||
|             result[5], | ||||
|             result[6], | ||||
|             self._servers.get_server_by_id(result[7]), | ||||
|             id=result[0], | ||||
|             result[8], | ||||
|             result[9], | ||||
|             id=result[0] | ||||
|         ) | ||||
|  | ||||
|     def get_client_by_discord_id(self, discord_id: int) -> Client: | ||||
| @@ -72,7 +74,9 @@ class ClientRepositoryService(ClientRepositoryABC): | ||||
|             result[5], | ||||
|             result[6], | ||||
|             self._servers.get_server_by_id(result[7]), | ||||
|             id=result[0], | ||||
|             result[8], | ||||
|             result[9], | ||||
|             id=result[0] | ||||
|         ) | ||||
|  | ||||
|     def find_client_by_discord_id(self, discord_id: int) -> Optional[Client]: | ||||
| @@ -83,9 +87,9 @@ class ClientRepositoryService(ClientRepositoryABC): | ||||
|         result = self._context.select(Client.get_select_by_discord_id_string(discord_id)) | ||||
|         if result is None or len(result) == 0: | ||||
|             return None | ||||
|  | ||||
|          | ||||
|         result = result[0] | ||||
|  | ||||
|          | ||||
|         return Client( | ||||
|             result[1], | ||||
|             result[2], | ||||
| @@ -94,7 +98,9 @@ class ClientRepositoryService(ClientRepositoryABC): | ||||
|             result[5], | ||||
|             result[6], | ||||
|             self._servers.get_server_by_id(result[7]), | ||||
|             id=result[0], | ||||
|             result[8], | ||||
|             result[9], | ||||
|             id=result[0] | ||||
|         ) | ||||
|  | ||||
|     def find_client_by_server_id(self, discord_id: int) -> Optional[Client]: | ||||
| @@ -105,9 +111,9 @@ class ClientRepositoryService(ClientRepositoryABC): | ||||
|         result = self._context.select(Client.get_select_by_server_id_string(discord_id)) | ||||
|         if result is None or len(result) == 0: | ||||
|             return None | ||||
|  | ||||
|          | ||||
|         result = result[0] | ||||
|  | ||||
|          | ||||
|         return Client( | ||||
|             result[1], | ||||
|             result[2], | ||||
| @@ -116,7 +122,9 @@ class ClientRepositoryService(ClientRepositoryABC): | ||||
|             result[5], | ||||
|             result[6], | ||||
|             self._servers.get_server_by_id(result[7]), | ||||
|             id=result[0], | ||||
|             result[8], | ||||
|             result[9], | ||||
|             id=result[0] | ||||
|         ) | ||||
|  | ||||
|     def find_client_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> Optional[Client]: | ||||
| @@ -127,9 +135,9 @@ class ClientRepositoryService(ClientRepositoryABC): | ||||
|         result = self._context.select(Client.get_select_by_discord_id_and_server_id_string(discord_id, server_id)) | ||||
|         if result is None or len(result) == 0: | ||||
|             return None | ||||
|  | ||||
|          | ||||
|         result = result[0] | ||||
|  | ||||
|          | ||||
|         return Client( | ||||
|             result[1], | ||||
|             result[2], | ||||
| @@ -138,7 +146,9 @@ class ClientRepositoryService(ClientRepositoryABC): | ||||
|             result[5], | ||||
|             result[6], | ||||
|             self._servers.get_server_by_id(result[7]), | ||||
|             id=result[0], | ||||
|             result[8], | ||||
|             result[9], | ||||
|             id=result[0] | ||||
|         ) | ||||
|  | ||||
|     def add_client(self, client: Client): | ||||
| @@ -156,14 +166,14 @@ class ClientRepositoryService(ClientRepositoryABC): | ||||
|     def _get_client_and_server(self, id: int, server_id: int) -> Client: | ||||
|         server = self._servers.find_server_by_discord_id(server_id) | ||||
|         if server is None: | ||||
|             self._logger.warn(__name__, f"Cannot find server by id {server_id}") | ||||
|             raise Exception("Value not found") | ||||
|  | ||||
|             self._logger.warn(__name__, f'Cannot find server by id {server_id}') | ||||
|             raise Exception('Value not found') | ||||
|          | ||||
|         client = self.find_client_by_discord_id_and_server_id(id, server.server_id) | ||||
|         if client is None: | ||||
|             self._logger.warn(__name__, f"Cannot find client by ids {id}@{server.server_id}") | ||||
|             raise Exception("Value not found") | ||||
|  | ||||
|             self._logger.warn(__name__, f'Cannot find client by ids {id}@{server.server_id}') | ||||
|             raise Exception('Value not found') | ||||
|          | ||||
|         return client | ||||
|  | ||||
|     def append_sent_message_count(self, client_id: int, server_id: int, value: int): | ||||
|   | ||||
| @@ -22,7 +22,12 @@ class ServerRepositoryService(ServerRepositoryABC): | ||||
|         self._logger.trace(__name__, f"Send SQL command: {Server.get_select_all_string()}") | ||||
|         results = self._context.select(Server.get_select_all_string()) | ||||
|         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 | ||||
|  | ||||
| @@ -54,7 +59,12 @@ class ServerRepositoryService(ServerRepositoryABC): | ||||
|     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)}") | ||||
|         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: | ||||
|         self._logger.trace( | ||||
| @@ -62,7 +72,12 @@ class ServerRepositoryService(ServerRepositoryABC): | ||||
|             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] | ||||
|         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]: | ||||
|         self._logger.trace( | ||||
| @@ -72,10 +87,15 @@ class ServerRepositoryService(ServerRepositoryABC): | ||||
|         result = self._context.select(Server.get_select_by_discord_id_string(discord_id)) | ||||
|         if result is None or len(result) == 0: | ||||
|             return None | ||||
|  | ||||
|          | ||||
|         result = result[0] | ||||
|  | ||||
|         return Server(result[1], result[2], result[3], id=result[0]) | ||||
|         return Server( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             result[3], | ||||
|             id=result[0] | ||||
|         ) | ||||
|  | ||||
|     def add_server(self, server: Server): | ||||
|         self._logger.trace(__name__, f"Send SQL command: {server.insert_string}") | ||||
|   | ||||
							
								
								
									
										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
									
								
							
							
								
								
									
										20
									
								
								kdb-bot/src/bot_graphql/abc/data_query_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								kdb-bot/src/bot_graphql/abc/data_query_abc.py
									
									
									
									
									
										Normal 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 | ||||
							
								
								
									
										68
									
								
								kdb-bot/src/bot_graphql/abc/filter_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								kdb-bot/src/bot_graphql/abc/filter_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| 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
									
								
							
							
								
								
									
										37
									
								
								kdb-bot/src/bot_graphql/filter/level_filter.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								kdb-bot/src/bot_graphql/filter/level_filter.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										38
									
								
								kdb-bot/src/bot_graphql/filter/server_filter.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								kdb-bot/src/bot_graphql/filter/server_filter.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| 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) | ||||
							
								
								
									
										37
									
								
								kdb-bot/src/bot_graphql/graphql_module.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								kdb-bot/src/bot_graphql/graphql_module.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| 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) | ||||
							
								
								
									
										7
									
								
								kdb-bot/src/bot_graphql/graphql_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								kdb-bot/src/bot_graphql/graphql_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| 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 | ||||
| } | ||||
							
								
								
									
										18
									
								
								kdb-bot/src/bot_graphql/mutation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								kdb-bot/src/bot_graphql/mutation.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| 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
									
								
							
							
								
								
									
										37
									
								
								kdb-bot/src/bot_graphql/mutations/level_mutation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								kdb-bot/src/bot_graphql/mutations/level_mutation.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| 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
									
								
							
							
								
								
									
										39
									
								
								kdb-bot/src/bot_graphql/queries/level_query.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								kdb-bot/src/bot_graphql/queries/level_query.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										44
									
								
								kdb-bot/src/bot_graphql/queries/server_query.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								kdb-bot/src/bot_graphql/queries/server_query.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| 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) | ||||
							
								
								
									
										28
									
								
								kdb-bot/src/bot_graphql/query.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								kdb-bot/src/bot_graphql/query.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| 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() | ||||
							
								
								
									
										24
									
								
								kdb-bot/src/bot_graphql/schema.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								kdb-bot/src/bot_graphql/schema.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| 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 | ||||
		Reference in New Issue
	
	Block a user