mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 19:44:20 +00:00
Maybe this was a bad idea afterall
This commit is contained in:
parent
e1c3270527
commit
d2c1f87798
6 changed files with 59 additions and 50 deletions
|
@ -2,7 +2,6 @@ import discord
|
||||||
import typing
|
import typing
|
||||||
import logging as _logging
|
import logging as _logging
|
||||||
from .generic import GenericBot
|
from .generic import GenericBot
|
||||||
from royalnet.commands import NullCommand
|
|
||||||
from ..utils import asyncify, Call, Command, discord_escape
|
from ..utils import asyncify, Call, Command, discord_escape
|
||||||
from ..error import UnregisteredError, NoneFoundError, TooManyFoundError, InvalidConfigError, RoyalnetResponseError
|
from ..error import UnregisteredError, NoneFoundError, TooManyFoundError, InvalidConfigError, RoyalnetResponseError
|
||||||
from ..network import RoyalnetConfig, Request, ResponseSuccess, ResponseError
|
from ..network import RoyalnetConfig, Request, ResponseSuccess, ResponseError
|
||||||
|
@ -32,7 +31,7 @@ class DiscordBot(GenericBot):
|
||||||
log.debug(f"Creating music_data dict")
|
log.debug(f"Creating music_data dict")
|
||||||
self.music_data: typing.Dict[discord.Guild, playmodes.PlayMode] = {}
|
self.music_data: typing.Dict[discord.Guild, playmodes.PlayMode] = {}
|
||||||
|
|
||||||
def _call_factory(self) -> typing.Type[Call]:
|
def _interface_factory(self) -> typing.Type[Call]:
|
||||||
log.debug(f"Creating DiscordCall")
|
log.debug(f"Creating DiscordCall")
|
||||||
|
|
||||||
# noinspection PyMethodParameters
|
# noinspection PyMethodParameters
|
||||||
|
|
|
@ -2,10 +2,11 @@ import sys
|
||||||
import typing
|
import typing
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from ..utils import Command, NetworkHandler, Call
|
from ..utils import NetworkHandler
|
||||||
from royalnet.commands import NullCommand
|
from ..network import RoyalnetLink, Request, Response, ResponseSuccess, ResponseError, RoyalnetConfig
|
||||||
from ..network import RoyalnetLink, Request, Response, ResponseError, RoyalnetConfig
|
|
||||||
from ..database import Alchemy, DatabaseConfig, relationshiplinkchain
|
from ..database import Alchemy, DatabaseConfig, relationshiplinkchain
|
||||||
|
from ..commands import Command, CommandInterface
|
||||||
|
from ..error import *
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@ -28,17 +29,40 @@ class GenericBot:
|
||||||
for command in commands:
|
for command in commands:
|
||||||
lower_command_name = command.command_name.lower()
|
lower_command_name = command.command_name.lower()
|
||||||
self.commands[f"{command_prefix}{lower_command_name}"] = command
|
self.commands[f"{command_prefix}{lower_command_name}"] = command
|
||||||
self.network_handlers = {**self.network_handlers, **command.network_handler_dict()}
|
|
||||||
self.missing_command: typing.Type[Command] = missing_command
|
self.missing_command: typing.Type[Command] = missing_command
|
||||||
self.error_command: typing.Type[Command] = error_command
|
self.error_command: typing.Type[Command] = error_command
|
||||||
log.debug(f"Successfully generated commands")
|
log.debug(f"Successfully generated commands")
|
||||||
|
|
||||||
def _call_factory(self) -> typing.Type[Call]:
|
def _interface_factory(self) -> typing.Type[CommandInterface]:
|
||||||
"""Create the TelegramCall class, representing a command call. It should inherit from :py:class:`royalnet.utils.Call`.
|
"""Create a :py:class:`royalnet.commands.CommandInterface` type and return it.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The created TelegramCall class."""
|
The created :py:class:`royalnet.commands.CommandInterface` type."""
|
||||||
raise NotImplementedError()
|
|
||||||
|
# noinspection PyAbstractClass,PyMethodParameters
|
||||||
|
class GenericInterface(CommandInterface):
|
||||||
|
alchemy = self.alchemy
|
||||||
|
bot = self
|
||||||
|
|
||||||
|
def register_net_handler(ci, message_type: str, network_handler: typing.Callable):
|
||||||
|
self.network_handlers[message_type] = network_handler
|
||||||
|
|
||||||
|
async def net_request(ci, request: Request, destination: str) -> dict:
|
||||||
|
if self.network is None:
|
||||||
|
raise InvalidConfigError("Royalnet is not enabled on this bot")
|
||||||
|
response_dict: dict = await self.network.request(request.to_dict(), destination)
|
||||||
|
if "type" not in response_dict:
|
||||||
|
raise RoyalnetResponseError("Response is missing a type")
|
||||||
|
elif response_dict["type"] == "ResponseSuccess":
|
||||||
|
response: typing.Union[ResponseSuccess, ResponseError] = ResponseSuccess.from_dict(response_dict)
|
||||||
|
elif response_dict["type"] == "ResponseError":
|
||||||
|
response = ResponseError.from_dict(response_dict)
|
||||||
|
else:
|
||||||
|
raise RoyalnetResponseError("Response type is unknown")
|
||||||
|
response.raise_on_error()
|
||||||
|
return response.data
|
||||||
|
|
||||||
|
return GenericInterface
|
||||||
|
|
||||||
def _init_royalnet(self, royalnet_config: RoyalnetConfig):
|
def _init_royalnet(self, royalnet_config: RoyalnetConfig):
|
||||||
"""Create a :py:class:`royalnet.network.RoyalnetLink`, and run it as a :py:class:`asyncio.Task`."""
|
"""Create a :py:class:`royalnet.network.RoyalnetLink`, and run it as a :py:class:`asyncio.Task`."""
|
||||||
|
@ -117,7 +141,7 @@ class GenericBot:
|
||||||
if commands is None:
|
if commands is None:
|
||||||
commands = []
|
commands = []
|
||||||
self._init_commands(command_prefix, commands, missing_command=missing_command, error_command=error_command)
|
self._init_commands(command_prefix, commands, missing_command=missing_command, error_command=error_command)
|
||||||
self._Call = self._call_factory()
|
self._Call = self._interface_factory()
|
||||||
if royalnet_config is None:
|
if royalnet_config is None:
|
||||||
self.network = None
|
self.network = None
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -3,11 +3,11 @@ import telegram.utils.request
|
||||||
import typing
|
import typing
|
||||||
import logging as _logging
|
import logging as _logging
|
||||||
from .generic import GenericBot
|
from .generic import GenericBot
|
||||||
from royalnet.commands import NullCommand
|
from ..utils import asyncify, telegram_escape
|
||||||
from ..utils import asyncify, Call, Command, telegram_escape
|
|
||||||
from ..error import UnregisteredError, InvalidConfigError, RoyalnetResponseError
|
from ..error import UnregisteredError, InvalidConfigError, RoyalnetResponseError
|
||||||
from ..network import RoyalnetConfig, Request, ResponseSuccess, ResponseError
|
from ..network import RoyalnetConfig, Request, ResponseSuccess, ResponseError
|
||||||
from ..database import DatabaseConfig
|
from ..database import DatabaseConfig
|
||||||
|
from ..commands import CommandInterface
|
||||||
|
|
||||||
|
|
||||||
log = _logging.getLogger(__name__)
|
log = _logging.getLogger(__name__)
|
||||||
|
@ -21,7 +21,6 @@ class TelegramConfig:
|
||||||
|
|
||||||
class TelegramBot(GenericBot):
|
class TelegramBot(GenericBot):
|
||||||
"""A bot that connects to `Telegram <https://telegram.org/>`_."""
|
"""A bot that connects to `Telegram <https://telegram.org/>`_."""
|
||||||
interface_name = "telegram"
|
|
||||||
|
|
||||||
def _init_client(self):
|
def _init_client(self):
|
||||||
"""Create the :py:class:`telegram.Bot`, and set the starting offset."""
|
"""Create the :py:class:`telegram.Bot`, and set the starting offset."""
|
||||||
|
@ -30,43 +29,29 @@ class TelegramBot(GenericBot):
|
||||||
self.client = telegram.Bot(self._telegram_config.token, request=request)
|
self.client = telegram.Bot(self._telegram_config.token, request=request)
|
||||||
self._offset: int = -100
|
self._offset: int = -100
|
||||||
|
|
||||||
def _call_factory(self) -> typing.Type[Call]:
|
def _interface_factory(self) -> typing.Type[CommandInterface]:
|
||||||
|
GenericInterface = super()._interface_factory()
|
||||||
|
|
||||||
# noinspection PyMethodParameters
|
# noinspection PyMethodParameters
|
||||||
class TelegramCall(Call):
|
class TelegramInterface(GenericInterface):
|
||||||
interface_name = self.interface_name
|
name = "telegram"
|
||||||
interface_obj = self
|
prefix = "/"
|
||||||
interface_prefix = "/"
|
|
||||||
|
|
||||||
alchemy = self.alchemy
|
alchemy = self.alchemy
|
||||||
|
|
||||||
async def reply(call, text: str):
|
async def reply(ci, extra: dict, text: str):
|
||||||
await asyncify(call.channel.send_message, telegram_escape(text),
|
await asyncify(ci.channel.send_message, telegram_escape(text),
|
||||||
parse_mode="HTML",
|
parse_mode="HTML",
|
||||||
disable_web_page_preview=True)
|
disable_web_page_preview=True)
|
||||||
|
|
||||||
async def net_request(call, request: Request, destination: str) -> dict:
|
async def get_author(ci, extra: dict, error_if_none=False):
|
||||||
if self.network is None:
|
update: telegram.Update = extra["update"]
|
||||||
raise InvalidConfigError("Royalnet is not enabled on this bot")
|
|
||||||
response_dict: dict = await self.network.request(request.to_dict(), destination)
|
|
||||||
if "type" not in response_dict:
|
|
||||||
raise RoyalnetResponseError("Response is missing a type")
|
|
||||||
elif response_dict["type"] == "ResponseSuccess":
|
|
||||||
response: typing.Union[ResponseSuccess, ResponseError] = ResponseSuccess.from_dict(response_dict)
|
|
||||||
elif response_dict["type"] == "ResponseError":
|
|
||||||
response = ResponseError.from_dict(response_dict)
|
|
||||||
else:
|
|
||||||
raise RoyalnetResponseError("Response type is unknown")
|
|
||||||
response.raise_on_error()
|
|
||||||
return response.data
|
|
||||||
|
|
||||||
async def get_author(call, error_if_none=False):
|
|
||||||
update: telegram.Update = call.kwargs["update"]
|
|
||||||
user: telegram.User = update.effective_user
|
user: telegram.User = update.effective_user
|
||||||
if user is None:
|
if user is None:
|
||||||
if error_if_none:
|
if error_if_none:
|
||||||
raise UnregisteredError("No author for this message")
|
raise UnregisteredError("No author for this message")
|
||||||
return None
|
return None
|
||||||
query = call.session.query(self.master_table)
|
query = ci.session.query(self.master_table)
|
||||||
for link in self.identity_chain:
|
for link in self.identity_chain:
|
||||||
query = query.join(link.mapper.class_)
|
query = query.join(link.mapper.class_)
|
||||||
query = query.filter(self.identity_column == user.id)
|
query = query.filter(self.identity_column == user.id)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import typing
|
import typing
|
||||||
from ..error import UnsupportedError
|
from ..error import UnsupportedError
|
||||||
from .commandinterface import CommandInterface
|
from .commandinterface import CommandInterface
|
||||||
|
from .commandargs import CommandArgs
|
||||||
|
|
||||||
|
|
||||||
class Command:
|
class Command:
|
||||||
|
@ -21,8 +22,5 @@ class Command:
|
||||||
def __init__(self, interface: CommandInterface):
|
def __init__(self, interface: CommandInterface):
|
||||||
self.interface = interface
|
self.interface = interface
|
||||||
|
|
||||||
async def common(self) -> None:
|
async def run(self, args: CommandArgs, **extra) -> None:
|
||||||
raise UnsupportedError(f"Command {self.name} can't be called on {self.interface.name}.")
|
raise UnsupportedError(f"Command {self.name} can't be called on {self.interface.name}.")
|
||||||
|
|
||||||
def __getattr__(self, item) -> typing.Callable:
|
|
||||||
return self.common
|
|
||||||
|
|
|
@ -13,32 +13,35 @@ class CommandInterface:
|
||||||
def __init__(self, alias: str):
|
def __init__(self, alias: str):
|
||||||
self.session = self.alchemy.Session()
|
self.session = self.alchemy.Session()
|
||||||
|
|
||||||
async def reply(self, text: str) -> None:
|
def register_net_handler(self, message_type: str, network_handler: typing.Callable):
|
||||||
|
"""Register a new handler for messages received through Royalnet."""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
async def reply(self, extra: dict, text: str) -> None:
|
||||||
"""Send a text message to the channel where the call was made.
|
"""Send a text message to the channel where the call was made.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
extra: The ``extra`` dict passed to the Command
|
||||||
text: The text to be sent, possibly formatted in the weird undescribed markup that I'm using."""
|
text: The text to be sent, possibly formatted in the weird undescribed markup that I'm using."""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
async def net_request(self, message, destination: str) -> dict:
|
async def net_request(self, extra: dict, message, destination: str) -> dict:
|
||||||
"""Send data through a :py:class:`royalnet.network.RoyalnetLink` and wait for a :py:class:`royalnet.network.Reply`.
|
"""Send data through a :py:class:`royalnet.network.RoyalnetLink` and wait for a :py:class:`royalnet.network.Reply`.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
extra: The ``extra`` dict passed to the Command
|
||||||
message: The data to be sent. Must be :py:mod:`pickle`-able.
|
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."""
|
destination: The destination of the request, either in UUID format or node name."""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
async def get_author(self, error_if_none: bool = False):
|
async def get_author(self, extra: dict, error_if_none: bool = False):
|
||||||
"""Try to find the identifier of the user that sent the message.
|
"""Try to find the identifier of the user that sent the message.
|
||||||
That probably means, the database row identifying the user.
|
That probably means, the database row identifying the user.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
extra: The ``extra`` dict passed to the Command
|
||||||
error_if_none: Raise a :py:exc:`royalnet.error.UnregisteredError` if this is True and the call has no author.
|
error_if_none: Raise a :py:exc:`royalnet.error.UnregisteredError` if this is True and the call has no author.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:py:exc:`royalnet.error.UnregisteredError` if ``error_if_none`` is set to True and no author is found."""
|
:py:exc:`royalnet.error.UnregisteredError` if ``error_if_none`` is set to True and no author is found."""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def register_net_handler(self, message_type: str, network_handler: typing.Callable):
|
|
||||||
"""Register a new handler for messages received through Royalnet."""
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
Loading…
Reference in a new issue