diff --git a/royalnet/commands/__init__.py b/royalnet/commands/__init__.py index 726c0206..edc24479 100644 --- a/royalnet/commands/__init__.py +++ b/royalnet/commands/__init__.py @@ -2,5 +2,15 @@ from .commandinterface import CommandInterface from .command import Command from .commanddata import CommandData from .commandargs import CommandArgs +from .commanderrors import CommandError, InvalidInputError, UnsupportedError, KeyboardExpiredError -__all__ = ["CommandInterface", "Command", "CommandData", "CommandArgs"] +__all__ = [ + "CommandInterface", + "Command", + "CommandData", + "CommandArgs", + "CommandError", + "InvalidInputError", + "UnsupportedError", + "KeyboardExpiredError", +] diff --git a/royalnet/commands/command.py b/royalnet/commands/command.py index 9b275787..1a8f710f 100644 --- a/royalnet/commands/command.py +++ b/royalnet/commands/command.py @@ -1,5 +1,4 @@ import typing -from ..error import UnsupportedError from .commandinterface import CommandInterface from .commandargs import CommandArgs from .commanddata import CommandData @@ -28,4 +27,4 @@ class Command: self.interface = interface async def run(self, args: CommandArgs, data: CommandData) -> None: - raise UnsupportedError(f"Command {self.name} can't be called on {self.interface.name}.") + raise NotImplementedError() diff --git a/royalnet/commands/commandargs.py b/royalnet/commands/commandargs.py index cd5e192d..c21e0b59 100644 --- a/royalnet/commands/commandargs.py +++ b/royalnet/commands/commandargs.py @@ -1,6 +1,6 @@ import re import typing -from royalnet.error import InvalidInputError +from .commanderrors import InvalidInputError class CommandArgs(list): diff --git a/royalnet/commands/commanddata.py b/royalnet/commands/commanddata.py index 4520d79c..b72daa88 100644 --- a/royalnet/commands/commanddata.py +++ b/royalnet/commands/commanddata.py @@ -1,4 +1,5 @@ import typing +from .commanderrors import UnsupportedError class CommandData: @@ -7,31 +8,28 @@ class CommandData: Parameters: text: The text to be sent, possibly formatted in the weird undescribed markup that I'm using.""" - raise NotImplementedError() + raise UnsupportedError("'reply' is not supported on this platform") async def get_author(self, error_if_none: bool = False): """Try to find the identifier of the user that sent the message. That probably means, the database row identifying the user. Parameters: - error_if_none: Raise a :py:exc:`royalnet.error.UnregisteredError` if this is True and the call has no author. - - Raises: - :py:exc:`royalnet.error.UnregisteredError` if ``error_if_none`` is set to True and no author is found.""" - raise NotImplementedError() + error_if_none: Raise an exception if this is True and the call has no author.""" + raise UnsupportedError("'get_author' is not supported on this platform") async def keyboard(self, text: str, keyboard: typing.Dict[str, typing.Callable]) -> None: """Send a keyboard having the keys of the dict as keys and calling the correspondent values on a press. The function should be passed the :py:class:`CommandData` instance as a argument.""" - raise NotImplementedError() + raise UnsupportedError("'keyboard' is not supported on this platform") - async def delete_invoking(self, error_if_unavailable=False): + async def delete_invoking(self, error_if_unavailable=False) -> None: """Delete the invoking message, if supported by the interface. The invoking message is the message send by the user that contains the command. Parameters: - error_if_unavailable: if True, raise NotImplementedError() if the message cannot been deleted""" + error_if_unavailable: if True, raise an exception if the message cannot been deleted.""" if error_if_unavailable: - raise NotImplementedError() + raise UnsupportedError("'delete_invoking' is not supported on this platform") diff --git a/royalnet/commands/commanderrors.py b/royalnet/commands/commanderrors.py new file mode 100644 index 00000000..c083ced8 --- /dev/null +++ b/royalnet/commands/commanderrors.py @@ -0,0 +1,25 @@ +class CommandError(Exception): + """Something went wrong during the execution of this command. + + Display an error message to the user, explaining what went wrong.""" + def __init__(self, message=""): + self.message = message + + def __repr__(self): + return f"{self.__class__.__qualname__}({repr(self.message)})" + + +class InvalidInputError(CommandError): + """The command has received invalid input and cannot complete. + + Display an error message to the user, along with the correct syntax for the command.""" + + +class UnsupportedError(CommandError): + """A requested feature is not available on this interface. + + Display an error message to the user, telling them to use another interface.""" + + +class KeyboardExpiredError(CommandError): + """A special type of exception that can be raised in keyboard handlers to mark a specific keyboard as expired.""" diff --git a/royalnet/commands/commandinterface.py b/royalnet/commands/commandinterface.py index d687ae55..331c366c 100644 --- a/royalnet/commands/commandinterface.py +++ b/royalnet/commands/commandinterface.py @@ -1,6 +1,6 @@ import typing import asyncio -from ..error import UnsupportedError +from .commanderrors import UnsupportedError if typing.TYPE_CHECKING: from ..database import Alchemy from ..bots import GenericBot @@ -21,11 +21,11 @@ class CommandInterface: def register_net_handler(self, message_type: str, network_handler: typing.Callable): """Register a new handler for messages received through Royalnet.""" - raise UnsupportedError() + raise UnsupportedError("'register_net_handler' is not supported on this platform") def unregister_net_handler(self, message_type: str): """Remove a Royalnet handler.""" - raise UnsupportedError() + raise UnsupportedError("'unregister_net_handler' is not supported on this platform") async def net_request(self, message, destination: str) -> dict: """Send data through a :py:class:`royalnet.network.NetworkLink` and wait for a @@ -34,10 +34,10 @@ class CommandInterface: 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() + raise UnsupportedError("'net_request' is not supported on this platform") def register_keyboard_key(self, key_name: str, callback: typing.Callable): - raise UnsupportedError() + raise UnsupportedError("'register_keyboard_key' is not supported on this platform") def unregister_keyboard_key(self, key_name: str): - raise UnsupportedError() + raise UnsupportedError("'unregister_keyboard_key' is not supported on this platform") diff --git a/royalnet/commands/royalmusic/__init__.py b/royalnet/commands/royalmusic/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/royalnet/commands/royalgames/pause.py b/royalnet/commands/royalmusic/pause.py similarity index 100% rename from royalnet/commands/royalgames/pause.py rename to royalnet/commands/royalmusic/pause.py diff --git a/royalnet/commands/royalgames/play.py b/royalnet/commands/royalmusic/play.py similarity index 90% rename from royalnet/commands/royalgames/play.py rename to royalnet/commands/royalmusic/play.py index a20d705a..dfcc6eae 100644 --- a/royalnet/commands/royalgames/play.py +++ b/royalnet/commands/royalmusic/play.py @@ -38,10 +38,7 @@ class PlayNH(NetworkHandler): "outtmpl": f"./downloads/{datetime.datetime.now().timestamp()}_%(title)s.%(ext)s" } # Start downloading - if data["url"].startswith("http://") or data["url"].startswith("https://"): - dfiles: typing.List[YtdlDiscord] = await asyncify(YtdlDiscord.create_from_url, data["url"], **ytdl_args) - else: - dfiles = await asyncify(YtdlDiscord.create_from_url, f"ytsearch:{data['url']}", **ytdl_args) + dfiles: typing. List[YtdlDiscord] = await asyncify(YtdlDiscord.create_from_url, data["url"], **ytdl_args) await bot.add_to_music_data(dfiles, guild) # Create response dictionary response = { @@ -66,6 +63,8 @@ class PlayCommand(Command): async def run(self, args: CommandArgs, data: CommandData) -> None: guild_name, url = args.match(r"(?:\[(.+)])?\s*?") + if not (url.startswith("http://") or url.startswith("https://")): + raise response = await self.interface.net_request(Request("music_play", {"url": url, "guild_name": guild_name}), "discord") if len(response["videos"]) == 0: await data.reply(f"⚠️ Nessun video trovato.") diff --git a/royalnet/commands/royalgames/playmode.py b/royalnet/commands/royalmusic/playmode.py similarity index 100% rename from royalnet/commands/royalgames/playmode.py rename to royalnet/commands/royalmusic/playmode.py diff --git a/royalnet/commands/royalgames/queue.py b/royalnet/commands/royalmusic/queue.py similarity index 100% rename from royalnet/commands/royalgames/queue.py rename to royalnet/commands/royalmusic/queue.py diff --git a/royalnet/commands/royalgames/skip.py b/royalnet/commands/royalmusic/skip.py similarity index 100% rename from royalnet/commands/royalgames/skip.py rename to royalnet/commands/royalmusic/skip.py diff --git a/royalnet/commands/royalgames/summon.py b/royalnet/commands/royalmusic/summon.py similarity index 100% rename from royalnet/commands/royalgames/summon.py rename to royalnet/commands/royalmusic/summon.py diff --git a/royalnet/error.py b/royalnet/error.py index 001965a0..79133af7 100644 --- a/royalnet/error.py +++ b/royalnet/error.py @@ -3,30 +3,6 @@ if typing.TYPE_CHECKING: from .network import ResponseError -class NoneFoundError(Exception): - """The element that was being looked for was not found.""" - - -class TooManyFoundError(Exception): - """Multiple elements matching the request were found, and only one was expected.""" - - -class UnregisteredError(Exception): - """The command required a registered user, and the user was not registered.""" - - -class UnsupportedError(Exception): - """The command is not supported for the specified interface.""" - - -class InvalidInputError(Exception): - """The command has received invalid input and cannot complete.""" - - -class InvalidConfigError(Exception): - """The bot has not been configured correctly, therefore the command can not function.""" - - class RoyalnetRequestError(Exception): """An error was raised while handling the Royalnet request. @@ -41,19 +17,3 @@ class RoyalnetRequestError(Exception): class RoyalnetResponseError(Exception): """The :py:class:`royalnet.network.Response` that was received is invalid.""" - - -class ExternalError(Exception): - """Something went wrong in a non-Royalnet component and the command execution cannot be completed.""" - - -class FileTooBigError(Exception): - """The file to be downloaded would be too big to store; therefore, it has been skipped.""" - - -class CurrentlyDisabledError(Exception): - """This feature is temporarely disabled and is not available right now.""" - - -class KeyboardExpiredError(Exception): - """A special type of exception that can be raised in keyboard handlers to mark a specific keyboard as expired."""