mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 19:44:20 +00:00
Do a lot of stuff
This commit is contained in:
parent
85468ec78d
commit
90f566107f
18 changed files with 121 additions and 88 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -2,10 +2,7 @@ config.ini
|
||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
__pycache__
|
__pycache__
|
||||||
diario.json
|
downloads/
|
||||||
libopus-0.dll
|
|
||||||
music.opus
|
|
||||||
opusfiles/
|
|
||||||
ignored/
|
ignored/
|
||||||
markovmodels/
|
markovmodels/
|
||||||
logs/
|
logs/
|
||||||
|
|
|
@ -2,4 +2,4 @@ from .playmodes import PlayMode, Playlist, Pool
|
||||||
from .youtubedl import YtdlFile, YtdlInfo
|
from .youtubedl import YtdlFile, YtdlInfo
|
||||||
from .royalaudiofile import RoyalAudioFile
|
from .royalaudiofile import RoyalAudioFile
|
||||||
|
|
||||||
__all__ = ["PlayMode", "Playlist", "Pool", "YtdlFile", "YtdlInfo"]
|
__all__ = ["PlayMode", "Playlist", "Pool", "YtdlFile", "YtdlInfo", "RoyalAudioFile"]
|
||||||
|
|
|
@ -4,10 +4,11 @@ import typing
|
||||||
import logging as _logging
|
import logging as _logging
|
||||||
import sys
|
import sys
|
||||||
from ..commands import NullCommand
|
from ..commands import NullCommand
|
||||||
from ..commands.summon import SummonMessage, SummonSuccessful, SummonError
|
from ..commands.summon import SummonMessage
|
||||||
from ..commands.play import PlayMessage, PlaySuccessful, PlayError
|
from ..commands.play import PlayMessage
|
||||||
from ..utils import asyncify, Call, Command, UnregisteredError
|
from ..utils import asyncify, Call, Command
|
||||||
from ..network import RoyalnetLink, Message
|
from royalnet.error import UnregisteredError
|
||||||
|
from ..network import RoyalnetLink, Message, RequestSuccessful, RequestError
|
||||||
from ..database import Alchemy, relationshiplinkchain
|
from ..database import Alchemy, relationshiplinkchain
|
||||||
from ..audio import RoyalAudioFile
|
from ..audio import RoyalAudioFile
|
||||||
|
|
||||||
|
@ -146,12 +147,12 @@ class DiscordBot:
|
||||||
if channel.name == message.channel_name:
|
if channel.name == message.channel_name:
|
||||||
matching_channels.append(channel)
|
matching_channels.append(channel)
|
||||||
if len(matching_channels) == 0:
|
if len(matching_channels) == 0:
|
||||||
return SummonError("No channels with a matching name found")
|
return RequestError("No channels with a matching name found")
|
||||||
elif len(matching_channels) > 1:
|
elif len(matching_channels) > 1:
|
||||||
return SummonError("Multiple channels with a matching name found")
|
return RequestError("Multiple channels with a matching name found")
|
||||||
matching_channel = matching_channels[0]
|
matching_channel = matching_channels[0]
|
||||||
await self.bot.vc_connect_or_move(matching_channel)
|
await self.bot.vc_connect_or_move(matching_channel)
|
||||||
return SummonSuccessful()
|
return RequestSuccessful()
|
||||||
|
|
||||||
async def nh_play(self, message: PlayMessage):
|
async def nh_play(self, message: PlayMessage):
|
||||||
# TODO: actually do what's intended to do
|
# TODO: actually do what's intended to do
|
||||||
|
@ -163,7 +164,7 @@ class DiscordBot:
|
||||||
for voice_client in self.bot.voice_clients:
|
for voice_client in self.bot.voice_clients:
|
||||||
voice_client: discord.VoiceClient
|
voice_client: discord.VoiceClient
|
||||||
voice_client.play(audio_source)
|
voice_client.play(audio_source)
|
||||||
return PlaySuccessful()
|
return RequestError()
|
||||||
|
|
||||||
async def run(self):
|
async def run(self):
|
||||||
await self.bot.login(self.token)
|
await self.bot.login(self.token)
|
||||||
|
|
|
@ -4,7 +4,8 @@ import typing
|
||||||
import logging as _logging
|
import logging as _logging
|
||||||
import sys
|
import sys
|
||||||
from ..commands import NullCommand
|
from ..commands import NullCommand
|
||||||
from ..utils import asyncify, Call, Command, UnregisteredError
|
from ..utils import asyncify, Call, Command
|
||||||
|
from royalnet.error import UnregisteredError
|
||||||
from ..network import RoyalnetLink, Message
|
from ..network import RoyalnetLink, Message
|
||||||
from ..database import Alchemy, relationshiplinkchain
|
from ..database import Alchemy, relationshiplinkchain
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import datetime
|
import datetime
|
||||||
import dateparser
|
import dateparser
|
||||||
from ..utils import Command, Call, InvalidInputError
|
from ..utils import Command, Call
|
||||||
|
from ..error import InvalidInputError
|
||||||
|
|
||||||
|
|
||||||
class DateparserCommand(Command):
|
class DateparserCommand(Command):
|
||||||
|
@ -11,9 +12,7 @@ class DateparserCommand(Command):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def common(cls, call: Call):
|
async def common(cls, call: Call):
|
||||||
if len(call.args) == 0:
|
text = call.args.joined(require_at_least=1)
|
||||||
raise InvalidInputError("Missing arg")
|
|
||||||
text = " ".join(call.args)
|
|
||||||
date: datetime.datetime = dateparser.parse(text)
|
date: datetime.datetime = dateparser.parse(text)
|
||||||
if date is None:
|
if date is None:
|
||||||
await call.reply("🕕 La data inserita non è valida.")
|
await call.reply("🕕 La data inserita non è valida.")
|
||||||
|
|
|
@ -4,7 +4,8 @@ import telegram
|
||||||
import typing
|
import typing
|
||||||
import os
|
import os
|
||||||
import aiohttp
|
import aiohttp
|
||||||
from ..utils import Command, Call, InvalidInputError, InvalidConfigError, ExternalError
|
from ..utils import Command, Call
|
||||||
|
from ..error import InvalidInputError, InvalidConfigError, ExternalError
|
||||||
from ..database.tables import Royal, Diario, Alias
|
from ..database.tables import Royal, Diario, Alias
|
||||||
from ..utils import asyncify
|
from ..utils import asyncify
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
import traceback
|
import traceback
|
||||||
from logging import Logger
|
from logging import Logger
|
||||||
from ..utils import Command, CommandArgs, Call, InvalidInputError, UnsupportedError, UnregisteredError
|
from ..utils import Command, CommandArgs, Call
|
||||||
|
from ..error import NoneFoundError, \
|
||||||
|
TooManyFoundError, \
|
||||||
|
UnregisteredError, \
|
||||||
|
UnsupportedError, \
|
||||||
|
InvalidInputError, \
|
||||||
|
InvalidConfigError, \
|
||||||
|
ExternalError
|
||||||
|
|
||||||
|
|
||||||
class ErrorHandlerCommand(Command):
|
class ErrorHandlerCommand(Command):
|
||||||
|
@ -16,13 +23,28 @@ class ErrorHandlerCommand(Command):
|
||||||
except InvalidInputError:
|
except InvalidInputError:
|
||||||
await call.reply("⚠️ Questo comando non può essere chiamato da solo.")
|
await call.reply("⚠️ Questo comando non può essere chiamato da solo.")
|
||||||
return
|
return
|
||||||
if e_type == InvalidInputError:
|
if e_type == NoneFoundError:
|
||||||
command = call.kwargs["previous_command"]
|
await call.reply("⚠️ L'elemento richiesto non è stato trovato.")
|
||||||
await call.reply(f"⚠️ Sintassi non valida.\nSintassi corretta: [c]{call.interface_prefix}{command.command_name} {command.command_syntax}[/c]")
|
return
|
||||||
|
if e_type == TooManyFoundError:
|
||||||
|
await call.reply("⚠️ La richiesta effettuata è ambigua, pertanto è stata annullata.")
|
||||||
return
|
return
|
||||||
if e_type == UnregisteredError:
|
if e_type == UnregisteredError:
|
||||||
await call.reply("⚠️ Devi essere registrato a Royalnet per usare questo comando!")
|
await call.reply("⚠️ Devi essere registrato a Royalnet per usare questo comando!")
|
||||||
return
|
return
|
||||||
|
if e_type == UnsupportedError:
|
||||||
|
await call.reply("⚠️ Il comando richiesto non è disponibile tramite questa interfaccia.")
|
||||||
|
return
|
||||||
|
if e_type == InvalidInputError:
|
||||||
|
command = call.kwargs["previous_command"]
|
||||||
|
await call.reply(f"⚠️ Sintassi non valida.\nSintassi corretta: [c]{call.interface_prefix}{command.command_name} {command.command_syntax}[/c]")
|
||||||
|
return
|
||||||
|
if e_type == InvalidConfigError:
|
||||||
|
await call.reply("⚠️ Il bot non è stato configurato correttamente, quindi questo comando non può essere eseguito. L'errore è stato segnalato all'amministratore.")
|
||||||
|
return
|
||||||
|
if e_type == ExternalError:
|
||||||
|
await call.reply("⚠️ Una risorsa esterna necessaria per l'esecuzione del comando non ha funzionato correttamente, quindi il comando è stato annullato.")
|
||||||
|
return
|
||||||
await call.reply(f"❌ Eccezione non gestita durante l'esecuzione del comando:\n[b]{e_type.__name__}[/b]\n{e_value}")
|
await call.reply(f"❌ Eccezione non gestita durante l'esecuzione del comando:\n[b]{e_type.__name__}[/b]\n{e_value}")
|
||||||
formatted_tb: str = '\n'.join(traceback.format_tb(e_tb))
|
formatted_tb: str = '\n'.join(traceback.format_tb(e_tb))
|
||||||
call.logger.error(f"Unhandled exception - {e_type.__name__}: {e_value}\n{formatted_tb}")
|
call.logger.error(f"Unhandled exception - {e_type.__name__}: {e_value}\n{formatted_tb}")
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
from ..utils import Command, Call, InvalidInputError
|
from ..utils import Command, Call
|
||||||
|
from royalnet.error import InvalidInputError
|
||||||
|
|
||||||
|
|
||||||
class PingCommand(Command):
|
class PingCommand(Command):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import typing
|
import typing
|
||||||
from ..utils import Command, Call
|
from ..utils import Command, Call
|
||||||
from ..network import Message
|
from ..network import Message, RequestSuccessful, RequestError
|
||||||
|
|
||||||
|
|
||||||
class PlayMessage(Message):
|
class PlayMessage(Message):
|
||||||
|
@ -8,15 +8,6 @@ class PlayMessage(Message):
|
||||||
self.url: str = url
|
self.url: str = url
|
||||||
|
|
||||||
|
|
||||||
class PlaySuccessful(Message):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class PlayError(Message):
|
|
||||||
def __init__(self, reason: str):
|
|
||||||
self.reason: str = reason
|
|
||||||
|
|
||||||
|
|
||||||
class PlayCommand(Command):
|
class PlayCommand(Command):
|
||||||
command_name = "play"
|
command_name = "play"
|
||||||
command_description = "Riproduce una canzone in chat vocale."
|
command_description = "Riproduce una canzone in chat vocale."
|
||||||
|
@ -25,11 +16,11 @@ class PlayCommand(Command):
|
||||||
@classmethod
|
@classmethod
|
||||||
async def common(cls, call: Call):
|
async def common(cls, call: Call):
|
||||||
url: str = call.args[0]
|
url: str = call.args[0]
|
||||||
response: typing.Union[PlaySuccessful, PlayError] = await call.net_request(PlayMessage(url), "discord")
|
response: typing.Union[RequestSuccessful, RequestError] = await call.net_request(PlayMessage(url), "discord")
|
||||||
if isinstance(response, PlayError):
|
if isinstance(response, RequestSuccessful):
|
||||||
await call.reply(f"⚠️ Si è verificato un'errore nella richiesta di riproduzione:\n[c]{response.reason}[/c]")
|
|
||||||
return
|
|
||||||
elif isinstance(response, PlaySuccessful):
|
|
||||||
await call.reply(f"✅ Richiesta la riproduzione di [c]{url}[/c].")
|
await call.reply(f"✅ Richiesta la riproduzione di [c]{url}[/c].")
|
||||||
return
|
return
|
||||||
|
elif isinstance(response, RequestError):
|
||||||
|
await call.reply(f"⚠️ Si è verificato un'errore nella richiesta di riproduzione:\n[c]{response.reason}[/c]")
|
||||||
|
return
|
||||||
raise TypeError(f"Received unexpected response in the PlayCommand: {response.__class__.__name__}")
|
raise TypeError(f"Received unexpected response in the PlayCommand: {response.__class__.__name__}")
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import typing
|
import typing
|
||||||
import discord
|
import discord
|
||||||
from ..utils import Command, Call
|
from ..utils import Command, Call
|
||||||
from ..network import Message
|
from ..network import Message, RequestSuccessful, RequestError
|
||||||
|
|
||||||
|
|
||||||
class SummonMessage(Message):
|
class SummonMessage(Message):
|
||||||
|
@ -9,15 +9,6 @@ class SummonMessage(Message):
|
||||||
self.channel_name: str = channel_name
|
self.channel_name: str = channel_name
|
||||||
|
|
||||||
|
|
||||||
class SummonSuccessful(Message):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class SummonError(Message):
|
|
||||||
def __init__(self, reason: str):
|
|
||||||
self.reason: str = reason
|
|
||||||
|
|
||||||
|
|
||||||
class SummonCommand(Command):
|
class SummonCommand(Command):
|
||||||
|
|
||||||
command_name = "summon"
|
command_name = "summon"
|
||||||
|
@ -27,11 +18,11 @@ class SummonCommand(Command):
|
||||||
@classmethod
|
@classmethod
|
||||||
async def common(cls, call: Call):
|
async def common(cls, call: Call):
|
||||||
channel_name: str = call.args[0].lstrip("#")
|
channel_name: str = call.args[0].lstrip("#")
|
||||||
response: typing.Union[SummonSuccessful, SummonError] = await call.net_request(SummonMessage(channel_name), "discord")
|
response: typing.Union[RequestSuccessful, RequestError] = await call.net_request(SummonMessage(channel_name), "discord")
|
||||||
if isinstance(response, SummonError):
|
if isinstance(response, RequestError):
|
||||||
await call.reply(f"⚠️ Si è verificato un'errore nella richiesta di connessione:\n[c]{response.reason}[/c]")
|
await call.reply(f"⚠️ Si è verificato un'errore nella richiesta di connessione:\n[c]{response.exc}[/c]")
|
||||||
return
|
return
|
||||||
elif isinstance(response, SummonSuccessful):
|
elif isinstance(response, RequestSuccessful):
|
||||||
await call.reply(f"✅ Mi sono connesso in [c]#{channel_name}[/c].")
|
await call.reply(f"✅ Mi sono connesso in [c]#{channel_name}[/c].")
|
||||||
return
|
return
|
||||||
raise TypeError(f"Received unexpected response type while summoning the bot: {response.__class__.__name__}")
|
raise TypeError(f"Received unexpected response type while summoning the bot: {response.__class__.__name__}")
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import typing
|
import typing
|
||||||
from telegram import Update, User
|
from telegram import Update, User
|
||||||
from discord import Message, Member
|
from discord import Message, Member
|
||||||
from ..utils import Command, Call, asyncify, UnsupportedError
|
from ..utils import Command, Call, asyncify
|
||||||
|
from royalnet.error import UnsupportedError
|
||||||
from ..database.tables import Royal, Telegram, Discord
|
from ..database.tables import Royal, Telegram, Discord
|
||||||
|
|
||||||
|
|
||||||
|
|
26
royalnet/error.py
Normal file
26
royalnet/error.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
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 ExternalError(Exception):
|
||||||
|
"""Something went wrong in a non-Royalnet component and the command execution cannot be completed."""
|
|
@ -1,4 +1,4 @@
|
||||||
from .messages import Message, ServerErrorMessage, InvalidSecretEM, InvalidDestinationEM, InvalidPackageEM
|
from .messages import Message, ServerErrorMessage, InvalidSecretEM, InvalidDestinationEM, InvalidPackageEM, RequestSuccessful, RequestError
|
||||||
from .packages import Package
|
from .packages import Package
|
||||||
from .royalnetlink import RoyalnetLink, NetworkError, NotConnectedError, NotIdentifiedError
|
from .royalnetlink import RoyalnetLink, NetworkError, NotConnectedError, NotIdentifiedError
|
||||||
from .royalnetserver import RoyalnetServer
|
from .royalnetserver import RoyalnetServer
|
||||||
|
@ -13,4 +13,6 @@ __all__ = ["Message",
|
||||||
"NotConnectedError",
|
"NotConnectedError",
|
||||||
"NotIdentifiedError",
|
"NotIdentifiedError",
|
||||||
"Package",
|
"Package",
|
||||||
"RoyalnetServer"]
|
"RoyalnetServer",
|
||||||
|
"RequestSuccessful",
|
||||||
|
"RequestError"]
|
||||||
|
|
|
@ -23,3 +23,12 @@ class InvalidPackageEM(ServerErrorMessage):
|
||||||
|
|
||||||
class InvalidDestinationEM(InvalidPackageEM):
|
class InvalidDestinationEM(InvalidPackageEM):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class RequestSuccessful(Message):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class RequestError(Message):
|
||||||
|
def __init__(self, exc: Exception):
|
||||||
|
self.exc = exc
|
||||||
|
|
|
@ -5,7 +5,7 @@ import functools
|
||||||
import typing
|
import typing
|
||||||
import pickle
|
import pickle
|
||||||
import logging as _logging
|
import logging as _logging
|
||||||
from .messages import Message, ServerErrorMessage
|
from .messages import Message, ServerErrorMessage, RequestError
|
||||||
from .packages import Package
|
from .packages import Package
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
|
@ -29,7 +29,7 @@ class NetworkError(Exception):
|
||||||
class PendingRequest:
|
class PendingRequest:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.event: asyncio.Event = asyncio.Event()
|
self.event: asyncio.Event = asyncio.Event()
|
||||||
self.data: Message = None
|
self.data: typing.Optional[Message] = None
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
if self.event.is_set():
|
if self.event.is_set():
|
||||||
|
@ -139,8 +139,11 @@ class RoyalnetLink:
|
||||||
# Package is a request
|
# Package is a request
|
||||||
assert isinstance(package, Package)
|
assert isinstance(package, Package)
|
||||||
log.debug(f"Received request {package.source_conv_id}: {package}")
|
log.debug(f"Received request {package.source_conv_id}: {package}")
|
||||||
|
try:
|
||||||
response = await self.request_handler(package.data)
|
response = await self.request_handler(package.data)
|
||||||
if response is not None:
|
except Exception as exc:
|
||||||
|
response = RequestError(exc=exc)
|
||||||
|
return
|
||||||
response_package: Package = package.reply(response)
|
response_package: Package = package.reply(response)
|
||||||
await self.send(response_package)
|
await self.send(response_package)
|
||||||
log.debug(f"Replied to request {response_package.source_conv_id}: {response_package}")
|
log.debug(f"Replied to request {response_package.source_conv_id}: {response_package}")
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
from .asyncify import asyncify
|
from .asyncify import asyncify
|
||||||
from .call import Call, UnregisteredError
|
from .call import Call
|
||||||
from .command import Command, CommandArgs, InvalidInputError, UnsupportedError, InvalidConfigError, ExternalError
|
from .command import Command, CommandArgs
|
||||||
from .safeformat import safeformat
|
from .safeformat import safeformat
|
||||||
from .classdictjanitor import cdj
|
from .classdictjanitor import cdj
|
||||||
from .sleepuntil import sleep_until
|
from .sleepuntil import sleep_until
|
||||||
from .plusformat import plusformat
|
from .plusformat import plusformat
|
||||||
|
|
||||||
__all__ = ["asyncify", "Call", "Command", "safeformat", "InvalidInputError", "UnsupportedError", "CommandArgs",
|
__all__ = ["asyncify", "Call", "Command", "safeformat", "CommandArgs",
|
||||||
"cdj", "InvalidConfigError", "ExternalError", "sleep_until", "UnregisteredError", "plusformat"]
|
"cdj", "sleep_until", "plusformat"]
|
||||||
|
|
|
@ -10,10 +10,6 @@ if typing.TYPE_CHECKING:
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
|
|
||||||
class UnregisteredError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Call:
|
class Call:
|
||||||
"""A command call. Still an abstract class, subbots should create a new call from this."""
|
"""A command call. Still an abstract class, subbots should create a new call from this."""
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,12 @@
|
||||||
import re
|
import re
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
|
from royalnet.error import InvalidInputError
|
||||||
|
|
||||||
if typing.TYPE_CHECKING:
|
if typing.TYPE_CHECKING:
|
||||||
from .call import Call
|
from .call import Call
|
||||||
|
|
||||||
|
|
||||||
class UnsupportedError(Exception):
|
|
||||||
"""The command is not supported for the specified source."""
|
|
||||||
|
|
||||||
|
|
||||||
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 ExternalError(Exception):
|
|
||||||
"""Something went wrong in a non-Royalnet component and the command cannot be executed fully."""
|
|
||||||
|
|
||||||
|
|
||||||
class CommandArgs(list):
|
class CommandArgs(list):
|
||||||
"""The arguments of a command. Raises InvalidInputError if the requested argument does not exist."""
|
"""The arguments of a command. Raises InvalidInputError if the requested argument does not exist."""
|
||||||
|
|
||||||
|
@ -36,8 +23,13 @@ class CommandArgs(list):
|
||||||
raise InvalidInputError(f'Tried to get invalid [{item}] slice from CommandArgs')
|
raise InvalidInputError(f'Tried to get invalid [{item}] slice from CommandArgs')
|
||||||
raise ValueError(f"Invalid type passed to CommandArgs.__getattr__: {type(item)}")
|
raise ValueError(f"Invalid type passed to CommandArgs.__getattr__: {type(item)}")
|
||||||
|
|
||||||
|
def joined(self, *, require_at_least=0):
|
||||||
|
if len(self) < require_at_least:
|
||||||
|
raise InvalidInputError("Not enough arguments")
|
||||||
|
return " ".join(self)
|
||||||
|
|
||||||
def match(self, pattern: typing.Pattern) -> typing.Match:
|
def match(self, pattern: typing.Pattern) -> typing.Match:
|
||||||
text = " ".join(self)
|
text = self.joined()
|
||||||
match = re.match(pattern, text)
|
match = re.match(pattern, text)
|
||||||
if match is None:
|
if match is None:
|
||||||
raise InvalidInputError("Pattern didn't match")
|
raise InvalidInputError("Pattern didn't match")
|
||||||
|
|
Loading…
Reference in a new issue