1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-27 21:44:21 +00:00

Some work on the Network Rework

This commit is contained in:
Steffo 2019-10-18 15:32:16 +02:00
parent 35638bb3cd
commit 9859d422f2
6 changed files with 41 additions and 63 deletions

View file

@ -1,7 +1,7 @@
bcrypt>=3.1.7 bcrypt>=3.1.7
discord.py>=1.2.2 discord.py>=1.2.2
python-telegram-bot>=11.1.0 python-telegram-bot>=11.1.0
royalherald>=5.0b4 royalherald>=5.0b7
pytest>=4.3.1 pytest>=4.3.1
psycopg2-binary>=2.8 psycopg2-binary>=2.8
aiohttp>=3.5.4 aiohttp>=3.5.4

View file

@ -28,7 +28,7 @@ class GenericBot:
self._Interface = self._interface_factory() self._Interface = self._interface_factory()
self._Data = self._data_factory() self._Data = self._data_factory()
self.commands = {} self.commands = {}
self.network_handlers: typing.Dict[str, typing.Type[NetworkHandler]] = {} self.network_handlers: typing.Dict[str, typing.Callable[[typing.Any], typing.Awaitable[typing.Dict]]] = {}
for SelectedCommand in self.uninitialized_commands: for SelectedCommand in self.uninitialized_commands:
interface = self._Interface() interface = self._Interface()
try: try:
@ -59,26 +59,25 @@ class GenericBot:
bot = self bot = self
loop = self.loop loop = self.loop
def register_net_handler(ci, message_type: str, network_handler: typing.Callable): def register_herald_action(ci,
self.network_handlers[message_type] = network_handler event_name: str,
coroutine: typing.Callable[[typing.Any], typing.Awaitable[typing.Dict]]) -> None:
self.network_handlers[event_name] = coroutine
def unregister_net_handler(ci, message_type: str): def unregister_herald_action(ci, event_name: str):
del self.network_handlers[message_type] del self.network_handlers[event_name]
async def net_request(ci, request: rh.Request, destination: str) -> dict: async def call_herald_action(ci, destination: str, event_name: str, args: typing.Dict) -> typing.Dict:
if self.network is None: if self.network is None:
raise Exception("Royalnet is not enabled on this bot") raise UnsupportedError("royalherald is not enabled on this bot")
response_dict: dict = await self.network.request(request.to_dict(), destination) request: rh.Request = rh.Request(handler=event_name, data=args)
if "type" not in response_dict: response: rh.Response = await self.network.request(destination=destination, request=request)
raise RoyalnetResponseError("Response is missing a type") if isinstance(response, rh.ResponseFailure):
elif response_dict["type"] == "ResponseSuccess": raise CommandError(f"royalherald action code failed: {response}")
response: typing.Union[rh.ResponseSuccess, rh.ResponseFailure] = rh.ResponseSuccess.from_dict(response_dict) elif isinstance(response, rh.ResponseSuccess):
elif response_dict["type"] == "ResponseError":
response = rh.ResponseFailure.from_dict(response_dict)
else:
raise RoyalnetResponseError("Response type is unknown")
response.raise_on_error()
return response.data return response.data
else:
raise TypeError(f"royalherald returned unknown response: {response}")
return GenericInterface return GenericInterface
@ -90,43 +89,31 @@ class GenericBot:
if self.uninitialized_network_config is not None: if self.uninitialized_network_config is not None:
self.network: rh.Link = rh.Link(self.uninitialized_network_config.master_uri, self.network: rh.Link = rh.Link(self.uninitialized_network_config.master_uri,
self.uninitialized_network_config.master_secret, self.uninitialized_network_config.master_secret,
self.interface_name, self._network_handler) self.interface_name,
self._network_handler)
log.debug(f"Running NetworkLink {self.network}") log.debug(f"Running NetworkLink {self.network}")
self.loop.create_task(self.network.run()) self.loop.create_task(self.network.run())
async def _network_handler(self, request_dict: dict) -> dict: async def _network_handler(self, request: rh.Request) -> rh.Response:
"""Handle a single :py:class:`dict` received from the :py:class:`royalherald.Link`.
Returns:
Another :py:class:`dict`, formatted as a :py:class:`royalherald.Response`."""
# Convert the dict to a Request
try:
request: rh.Request = rh.Request.from_dict(request_dict)
except TypeError:
log.warning(f"Invalid request received: {request_dict}")
return rh.ResponseFailure("invalid_request",
f"The Request that you sent was invalid. Check extra_info to see what you sent.",
extra_info={"you_sent": request_dict}).to_dict()
log.debug(f"Received {request} from the NetworkLink")
try: try:
network_handler = self.network_handlers[request.handler] network_handler = self.network_handlers[request.handler]
except KeyError: except KeyError:
log.warning(f"Missing network_handler for {request.handler}") log.warning(f"Missing network_handler for {request.handler}")
return rh.ResponseFailure("no_handler", f"This Link is missing a network handler for {request.handler}.").to_dict() return rh.ResponseFailure("no_handler", f"This bot is missing a network handler for {request.handler}.")
try: else:
log.debug(f"Using {network_handler} as handler for {request.handler}") log.debug(f"Using {network_handler} as handler for {request.handler}")
response: typing.Union[rh.ResponseSuccess, rh.ResponseFailure] = await getattr(network_handler, self.interface_name)(self, request.data) try:
return response.to_dict() response_data = await network_handler(**request.data)
return rh.ResponseSuccess(data=response_data)
except Exception as e: except Exception as e:
sentry_sdk.capture_exception(e) sentry_sdk.capture_exception(e)
log.debug(f"Exception {e} in {network_handler}") log.error(f"Exception {e} in {network_handler}")
return rh.ResponseFailure("exception_in_handler", return rh.ResponseFailure("exception_in_handler",
f"An exception was raised in {network_handler} for {request.handler}. Check " f"An exception was raised in {network_handler} for {request.handler}.",
f"extra_info for details.",
extra_info={ extra_info={
"type": e.__class__.__name__, "type": e.__class__.__name__,
"str": str(e) "message": str(e)
}).to_dict() })
def _init_database(self): def _init_database(self):
"""Create an :py:class:`royalnet.database.Alchemy` with the tables required by the packs. Then, """Create an :py:class:`royalnet.database.Alchemy` with the tables required by the packs. Then,

View file

@ -1,5 +1,6 @@
import typing import typing
import asyncio import asyncio
import royalherald as rh
from .commanderrors import UnsupportedError from .commanderrors import UnsupportedError
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
from .command import Command from .command import Command
@ -17,25 +18,19 @@ class CommandInterface:
def __init__(self): def __init__(self):
self.command: typing.Optional[Command] = None # Will be bound after the command has been created self.command: typing.Optional[Command] = None # Will be bound after the command has been created
def register_net_handler(self, message_type: str, network_handler: typing.Callable): def register_herald_action(self,
"""Register a new handler for messages received through Royalnet.""" event_name: str,
raise UnsupportedError("'register_net_handler' is not supported on this platform") coroutine: typing.Callable[[typing.Any], typing.Awaitable[typing.Dict]]):
raise UnsupportedError(f"{self.register_herald_action.__name__} is not supported on this platform")
def unregister_net_handler(self, message_type: str): def unregister_herald_action(self, event_name: str):
"""Remove a Royalnet handler.""" raise UnsupportedError(f"{self.unregister_herald_action.__name__} is not supported on this platform")
raise UnsupportedError("'unregister_net_handler' is not supported on this platform")
async def net_request(self, message, destination: str) -> dict: async def call_herald_action(self, destination: str, event_name: str, args: typing.Dict) -> typing.Dict:
"""Send data through a :py:class:`royalnet.network.NetworkLink` and wait for a raise UnsupportedError(f"{self.call_herald_action.__name__} is not supported on this platform")
:py:class:`royalnet.network.Reply`.
Parameters:
message: The data to be sent. Must be :py:mod:`pickle`-able.
destination: The destination of the request, either in UUID format or node name."""
raise UnsupportedError("'net_request' is not supported on this platform")
def register_keyboard_key(self, key_name: str, callback: typing.Callable): def register_keyboard_key(self, key_name: str, callback: typing.Callable):
raise UnsupportedError("'register_keyboard_key' is not supported on this platform") raise UnsupportedError(f"{self.register_keyboard_key.__name__} is not supported on this platform")
def unregister_keyboard_key(self, key_name: str): def unregister_keyboard_key(self, key_name: str):
raise UnsupportedError("'unregister_keyboard_key' is not supported on this platform") raise UnsupportedError(f"{self.unregister_keyboard_key.__name__} is not supported on this platform")

View file

@ -1,4 +0,0 @@
class NetworkHandler:
"""The NetworkHandler functions are called when a specific Message type is received."""
message_type = NotImplemented

View file

@ -16,7 +16,7 @@ setuptools.setup(
packages=setuptools.find_packages(), packages=setuptools.find_packages(),
install_requires=["python-telegram-bot>=11.1.0", install_requires=["python-telegram-bot>=11.1.0",
"discord.py>=1.0.1", "discord.py>=1.0.1",
"royalherald>=5.0b4", "royalherald>=5.0b7",
"psycopg2-binary>=2.8", "psycopg2-binary>=2.8",
"aiohttp>=3.5.4", "aiohttp>=3.5.4",
"sqlalchemy>=1.3.2", "sqlalchemy>=1.3.2",