Moved to ariadne
This commit is contained in:
parent
75500076a7
commit
b13695b018
@ -29,8 +29,8 @@
|
|||||||
"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",
|
||||||
"graphene==3.2.1",
|
"ariadne==0.17.0",
|
||||||
"graphql-server==3.0.0b5"
|
"ariadne-graphql-modules==0.7.0"
|
||||||
],
|
],
|
||||||
"DevDependencies": [
|
"DevDependencies": [
|
||||||
"cpl-cli==2022.12.0"
|
"cpl-cli==2022.12.0"
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import re
|
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
import uuid
|
import uuid
|
||||||
@ -12,7 +11,6 @@ from eventlet import wsgi
|
|||||||
from flask import Flask, request, jsonify, Response
|
from flask import Flask, request, jsonify, Response
|
||||||
from flask_cors import CORS
|
from flask_cors import CORS
|
||||||
from flask_socketio import SocketIO
|
from flask_socketio import SocketIO
|
||||||
from graphql_server.flask import GraphQLView
|
|
||||||
from werkzeug.exceptions import NotFound
|
from werkzeug.exceptions import NotFound
|
||||||
|
|
||||||
from bot_api.configuration.api_settings import ApiSettings
|
from bot_api.configuration.api_settings import ApiSettings
|
||||||
@ -23,7 +21,6 @@ from bot_api.exception.service_exception import ServiceException
|
|||||||
from bot_api.logging.api_logger import ApiLogger
|
from bot_api.logging.api_logger import ApiLogger
|
||||||
from bot_api.model.error_dto import ErrorDTO
|
from bot_api.model.error_dto import ErrorDTO
|
||||||
from bot_api.route.route import Route
|
from bot_api.route.route import Route
|
||||||
from bot_data.graphql.graphql import GraphQL
|
|
||||||
|
|
||||||
|
|
||||||
class Api(Flask):
|
class Api(Flask):
|
||||||
@ -64,16 +61,6 @@ class Api(Flask):
|
|||||||
|
|
||||||
self._requests = {}
|
self._requests = {}
|
||||||
|
|
||||||
gql = GraphQL()
|
|
||||||
self.add_url_rule(
|
|
||||||
'/api/graphql',
|
|
||||||
view_func=GraphQLView.as_view(
|
|
||||||
'graphql',
|
|
||||||
schema=gql.schema,
|
|
||||||
graphiql=True # for having the GraphiQL interface
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_methods_from_registered_route() -> Union[list[str], str]:
|
def _get_methods_from_registered_route() -> Union[list[str], str]:
|
||||||
methods = ['Unknown']
|
methods = ['Unknown']
|
||||||
|
@ -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
|
||||||
@ -47,6 +48,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)
|
||||||
|
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 ariadne_graphql_modules import make_executable_schema
|
||||||
|
from cpl_core.configuration import ConfigurationABC
|
||||||
|
from cpl_core.environment import ApplicationEnvironmentABC
|
||||||
|
from flask import request, jsonify
|
||||||
|
|
||||||
|
from bot_api.logging.api_logger import ApiLogger
|
||||||
|
from bot_api.route.route import Route
|
||||||
|
from bot_data.abc.query_abc import QueryABC
|
||||||
|
from bot_data.graphql.query import Query
|
||||||
|
|
||||||
|
|
||||||
|
class GraphQLController:
|
||||||
|
BasePath = f'/api/graphql'
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
config: ConfigurationABC,
|
||||||
|
env: ApplicationEnvironmentABC,
|
||||||
|
logger: ApiLogger,
|
||||||
|
):
|
||||||
|
self._config = config
|
||||||
|
self._env = env
|
||||||
|
self._logger = logger
|
||||||
|
|
||||||
|
@Route.get(f'{BasePath}/playground')
|
||||||
|
async def playground(self):
|
||||||
|
return PLAYGROUND_HTML, 200
|
||||||
|
|
||||||
|
@Route.post(f'{BasePath}')
|
||||||
|
async def graphql(self):
|
||||||
|
QueryABC.init()
|
||||||
|
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(
|
||||||
|
make_executable_schema(Query),
|
||||||
|
data,
|
||||||
|
context_value=request
|
||||||
|
)
|
||||||
|
|
||||||
|
return jsonify(result), 200 if success else 400
|
@ -1,6 +1,7 @@
|
|||||||
|
from ariadne_graphql_modules import ObjectType
|
||||||
from cpl_core.dependency_injection import ServiceProviderABC
|
from cpl_core.dependency_injection import ServiceProviderABC
|
||||||
|
from cpl_discord.service import DiscordBotServiceABC
|
||||||
from cpl_query.extension import List
|
from cpl_query.extension import List
|
||||||
from graphene import ObjectType
|
|
||||||
|
|
||||||
from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC
|
from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC
|
||||||
from bot_data.abc.client_repository_abc import ClientRepositoryABC
|
from bot_data.abc.client_repository_abc import ClientRepositoryABC
|
||||||
@ -18,9 +19,12 @@ from bot_data.model.server import Server
|
|||||||
from bot_data.model.user import User
|
from bot_data.model.user import User
|
||||||
from bot_data.model.user_joined_server import UserJoinedServer
|
from bot_data.model.user_joined_server import UserJoinedServer
|
||||||
from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel
|
from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel
|
||||||
|
from modules.level.service.level_service import LevelService
|
||||||
|
|
||||||
|
|
||||||
class QueryABC(ObjectType):
|
class QueryABC(ObjectType):
|
||||||
|
__abstract__ = True
|
||||||
|
|
||||||
_auto_roles: List[AutoRole]
|
_auto_roles: List[AutoRole]
|
||||||
_clients: List[Client]
|
_clients: List[Client]
|
||||||
_known_users: List[KnownUser]
|
_known_users: List[KnownUser]
|
||||||
@ -30,6 +34,9 @@ class QueryABC(ObjectType):
|
|||||||
_user_joined_voice_channel: List[UserJoinedVoiceChannel]
|
_user_joined_voice_channel: List[UserJoinedVoiceChannel]
|
||||||
_users: List[User]
|
_users: List[User]
|
||||||
|
|
||||||
|
_bot: DiscordBotServiceABC
|
||||||
|
_level_service: LevelService
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ServiceProviderABC.inject
|
@ServiceProviderABC.inject
|
||||||
def init(
|
def init(
|
||||||
@ -42,6 +49,8 @@ class QueryABC(ObjectType):
|
|||||||
user_joined_servers: UserJoinedServerRepositoryABC,
|
user_joined_servers: UserJoinedServerRepositoryABC,
|
||||||
user_joined_voice_channel: UserJoinedVoiceChannelRepositoryABC,
|
user_joined_voice_channel: UserJoinedVoiceChannelRepositoryABC,
|
||||||
users: UserRepositoryABC,
|
users: UserRepositoryABC,
|
||||||
|
bot: DiscordBotServiceABC,
|
||||||
|
level_service: LevelService,
|
||||||
):
|
):
|
||||||
cls._auto_roles = auto_roles.get_auto_roles()
|
cls._auto_roles = auto_roles.get_auto_roles()
|
||||||
cls._clients = clients.get_clients()
|
cls._clients = clients.get_clients()
|
||||||
@ -51,3 +60,5 @@ class QueryABC(ObjectType):
|
|||||||
cls._user_joined_servers = user_joined_servers.get_user_joined_servers()
|
cls._user_joined_servers = user_joined_servers.get_user_joined_servers()
|
||||||
cls._user_joined_voice_channel = user_joined_voice_channel.get_user_joined_voice_channels()
|
cls._user_joined_voice_channel = user_joined_voice_channel.get_user_joined_voice_channels()
|
||||||
cls._users = users.get_users()
|
cls._users = users.get_users()
|
||||||
|
cls._bot = bot
|
||||||
|
cls._level_service = level_service
|
@ -1,16 +0,0 @@
|
|||||||
import graphene
|
|
||||||
from graphene import Schema
|
|
||||||
|
|
||||||
from bot_data.abc.queryABC import QueryABC
|
|
||||||
from bot_data.graphql.root_query import RootQuery
|
|
||||||
|
|
||||||
|
|
||||||
class GraphQL:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
QueryABC.init()
|
|
||||||
self._schema = graphene.Schema(query=RootQuery)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def schema(self) -> Schema:
|
|
||||||
return self._schema
|
|
64
kdb-bot/src/bot_data/graphql/model.gql
Normal file
64
kdb-bot/src/bot_data/graphql/model.gql
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
type Query {
|
||||||
|
servers: [Server]
|
||||||
|
known_users: [User]
|
||||||
|
}
|
||||||
|
|
||||||
|
type Server {
|
||||||
|
id: ID
|
||||||
|
discord_id: String
|
||||||
|
clients: [Client]
|
||||||
|
members: [User]
|
||||||
|
level: [Level]
|
||||||
|
}
|
||||||
|
|
||||||
|
type Client {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
type User {
|
||||||
|
id: ID
|
||||||
|
discord_id: String
|
||||||
|
name: String
|
||||||
|
xp: Int
|
||||||
|
ontime: Int
|
||||||
|
level: Level
|
||||||
|
|
||||||
|
joined_servers: [UserJoinedServer]
|
||||||
|
joined_voice_channel: [UserJoinedVoiceChannel]
|
||||||
|
|
||||||
|
server: Server
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserJoinedServer {
|
||||||
|
id: ID
|
||||||
|
user: User
|
||||||
|
server: Server
|
||||||
|
joined_on: String
|
||||||
|
leaved_on: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserJoinedVoiceChannel {
|
||||||
|
id: ID
|
||||||
|
channel_id: String
|
||||||
|
user: User
|
||||||
|
joined_on: String
|
||||||
|
leaved_on: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type Level {
|
||||||
|
id: ID
|
||||||
|
name: String
|
||||||
|
color: String
|
||||||
|
min_xp: Int
|
||||||
|
permissions: String
|
||||||
|
|
||||||
|
server: Server
|
||||||
|
}
|
@ -1,12 +0,0 @@
|
|||||||
import graphene
|
|
||||||
|
|
||||||
from bot_data.abc.queryABC import QueryABC
|
|
||||||
from bot_data.graphql.types.client_query_type import ClientQueryType
|
|
||||||
|
|
||||||
|
|
||||||
class ClientQuery(QueryABC):
|
|
||||||
clients = graphene.List(ClientQueryType)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resolve_clients(cls, root, info):
|
|
||||||
return cls._clients
|
|
@ -1,19 +0,0 @@
|
|||||||
import graphene
|
|
||||||
from cpl_core.dependency_injection import ServiceProviderABC
|
|
||||||
|
|
||||||
from bot_data.abc.queryABC import QueryABC
|
|
||||||
from bot_data.graphql.types.server_query_type import ServerQueryType
|
|
||||||
from bot_data.service.server_repository_service import ServerRepositoryService
|
|
||||||
|
|
||||||
|
|
||||||
class ServerQuery(QueryABC):
|
|
||||||
servers = graphene.List(ServerQueryType)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
@ServiceProviderABC.inject
|
|
||||||
def _get_servers(servers: ServerRepositoryService):
|
|
||||||
return servers.get_servers()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def resolve_servers(cls, root, info):
|
|
||||||
return cls._servers
|
|
17
kdb-bot/src/bot_data/graphql/query.py
Normal file
17
kdb-bot/src/bot_data/graphql/query.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from ariadne import gql
|
||||||
|
|
||||||
|
from bot_data.abc.query_abc import QueryABC
|
||||||
|
from bot_data.graphql.types.server_query_type import ServerQueryType
|
||||||
|
|
||||||
|
|
||||||
|
class Query(QueryABC):
|
||||||
|
__schema__ = gql("""
|
||||||
|
type Query {
|
||||||
|
servers: [Server]
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
__requires__ = [ServerQueryType]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def resolve_servers(cls, *_):
|
||||||
|
return cls._servers
|
@ -1,10 +0,0 @@
|
|||||||
from graphene import ObjectType, relay
|
|
||||||
|
|
||||||
from bot_data.graphql.queries.server_query import ServerQuery
|
|
||||||
|
|
||||||
|
|
||||||
class RootQuery(
|
|
||||||
ServerQuery,
|
|
||||||
ObjectType
|
|
||||||
):
|
|
||||||
node = relay.Node.Field()
|
|
@ -1,18 +1,22 @@
|
|||||||
from graphene import Int, String
|
from ariadne import gql
|
||||||
|
|
||||||
from bot_data.abc.queryABC import QueryABC
|
from bot_data.abc.query_abc import QueryABC
|
||||||
from bot_data.model.client import Client
|
from bot_data.model.client import Client
|
||||||
|
|
||||||
|
|
||||||
class ClientQueryType(QueryABC):
|
class ClientQueryType(QueryABC):
|
||||||
id = Int()
|
__schema__ = gql("""
|
||||||
discord_id = String()
|
type Client {
|
||||||
sent_message_count = Int()
|
id: ID
|
||||||
received_message_count = Int()
|
discord_id: String
|
||||||
deleted_message_count = Int()
|
sent_message_count: Int
|
||||||
received_command_count = Int()
|
received_message_count: Int
|
||||||
moved_users_count = Int()
|
deleted_message_count: Int
|
||||||
|
received_command_count: Int
|
||||||
|
moved_users_count: Int
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
|
||||||
@staticmethod
|
@classmethod
|
||||||
def resolve_id(client: Client, info):
|
def resolve_id(cls, client: Client, *_):
|
||||||
return client.client_id
|
return client.client_id
|
||||||
|
21
kdb-bot/src/bot_data/graphql/types/level_query_type.py
Normal file
21
kdb-bot/src/bot_data/graphql/types/level_query_type.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
from ariadne import gql
|
||||||
|
|
||||||
|
from bot_data.abc.query_abc import QueryABC
|
||||||
|
from bot_data.model.client import Client
|
||||||
|
from bot_data.model.level import Level
|
||||||
|
|
||||||
|
|
||||||
|
class LevelQueryType(QueryABC):
|
||||||
|
__schema__ = gql("""
|
||||||
|
type Level {
|
||||||
|
id: ID
|
||||||
|
name: String
|
||||||
|
color: String
|
||||||
|
min_xp: Int
|
||||||
|
permissions: String
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
|
||||||
|
# @classmethod
|
||||||
|
# def resolve_id(cls, level: Level, *_):
|
||||||
|
# return level.id
|
@ -1,23 +1,40 @@
|
|||||||
from graphene import Int, DateTime, String, List
|
from ariadne import gql
|
||||||
|
|
||||||
from bot_data.abc.queryABC import QueryABC
|
from bot_data.abc.query_abc import QueryABC
|
||||||
from bot_data.graphql.types.client_query_type import ClientQueryType
|
from bot_data.graphql.types.client_query_type import ClientQueryType
|
||||||
|
from bot_data.graphql.types.level_query_type import LevelQueryType
|
||||||
|
from bot_data.graphql.types.user_query_type import UserQueryType
|
||||||
from bot_data.model.server import Server
|
from bot_data.model.server import Server
|
||||||
|
|
||||||
|
|
||||||
class ServerQueryType(QueryABC):
|
class ServerQueryType(QueryABC):
|
||||||
id = Int()
|
__schema__ = gql("""
|
||||||
discord_server_id = String()
|
type Server {
|
||||||
|
id: ID
|
||||||
|
discord_id: String
|
||||||
|
clients: [Client]
|
||||||
|
users: [User]
|
||||||
|
levels: [Level]
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
__requires__ = [ClientQueryType, UserQueryType, LevelQueryType]
|
||||||
|
|
||||||
created_at = DateTime()
|
@classmethod
|
||||||
modified_at = DateTime()
|
def resolve_id(cls, server: Server, *_):
|
||||||
|
|
||||||
clients = List(ClientQueryType)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def resolve_id(server: Server, info):
|
|
||||||
return server.server_id
|
return server.server_id
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def resolve_clients(cls, server: Server, info):
|
def resolve_discord_id(cls, server: Server, *_):
|
||||||
|
return server.discord_server_id
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def resolve_clients(cls, server: Server, *_):
|
||||||
return cls._clients.where(lambda c: c.server.server_id == server.server_id)
|
return cls._clients.where(lambda c: c.server.server_id == server.server_id)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def resolve_users(cls, server: Server, *_):
|
||||||
|
return cls._users.where(lambda u: u.server.server_id == server.server_id)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def resolve_levels(cls, server: Server, *_):
|
||||||
|
return cls._levels.where(lambda l: l.server.server_id == server.server_id)
|
||||||
|
39
kdb-bot/src/bot_data/graphql/types/user_query_type.py
Normal file
39
kdb-bot/src/bot_data/graphql/types/user_query_type.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
from ariadne import gql
|
||||||
|
|
||||||
|
from bot_data.abc.query_abc import QueryABC
|
||||||
|
from bot_data.graphql.types.level_query_type import LevelQueryType
|
||||||
|
from bot_data.model.user import User
|
||||||
|
|
||||||
|
|
||||||
|
class UserQueryType(QueryABC):
|
||||||
|
__schema__ = gql("""
|
||||||
|
type User {
|
||||||
|
id: ID
|
||||||
|
discord_id: String
|
||||||
|
name: String
|
||||||
|
xp: Int
|
||||||
|
ontime: Int
|
||||||
|
level: Level
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
__requires__ = [LevelQueryType]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def resolve_id(cls, user: User, *_):
|
||||||
|
return user.user_id
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def resolve_name(cls, user: User, *_):
|
||||||
|
return cls._bot.get_user(user.discord_id).name
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def resolve_ontime(cls, user: User, *_):
|
||||||
|
return cls._user_joined_voice_channel.where(lambda ujvc: ujvc.user.user_id == user.user_id) \
|
||||||
|
.where(lambda x: x.leaved_on is not None and x.joined_on is not None) \
|
||||||
|
.sum(lambda join: round((join.leaved_on - join.joined_on).total_seconds() / 3600, 2))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def resolve_level(cls, user: User, *_):
|
||||||
|
levels = cls._levels.where(lambda l: l.server.server_id == user.server.server_id).order_by(lambda l: l.min_xp)
|
||||||
|
return levels.where(lambda l: user.xp >= l.min_xp).last_or_default()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user