mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-12-03 16:24: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/
|
||||
.vscode/
|
||||
__pycache__
|
||||
diario.json
|
||||
libopus-0.dll
|
||||
music.opus
|
||||
opusfiles/
|
||||
downloads/
|
||||
ignored/
|
||||
markovmodels/
|
||||
logs/
|
||||
|
|
|
@ -2,4 +2,4 @@ from .playmodes import PlayMode, Playlist, Pool
|
|||
from .youtubedl import YtdlFile, YtdlInfo
|
||||
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 sys
|
||||
from ..commands import NullCommand
|
||||
from ..commands.summon import SummonMessage, SummonSuccessful, SummonError
|
||||
from ..commands.play import PlayMessage, PlaySuccessful, PlayError
|
||||
from ..utils import asyncify, Call, Command, UnregisteredError
|
||||
from ..network import RoyalnetLink, Message
|
||||
from ..commands.summon import SummonMessage
|
||||
from ..commands.play import PlayMessage
|
||||
from ..utils import asyncify, Call, Command
|
||||
from royalnet.error import UnregisteredError
|
||||
from ..network import RoyalnetLink, Message, RequestSuccessful, RequestError
|
||||
from ..database import Alchemy, relationshiplinkchain
|
||||
from ..audio import RoyalAudioFile
|
||||
|
||||
|
@ -146,12 +147,12 @@ class DiscordBot:
|
|||
if channel.name == message.channel_name:
|
||||
matching_channels.append(channel)
|
||||
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:
|
||||
return SummonError("Multiple channels with a matching name found")
|
||||
return RequestError("Multiple channels with a matching name found")
|
||||
matching_channel = matching_channels[0]
|
||||
await self.bot.vc_connect_or_move(matching_channel)
|
||||
return SummonSuccessful()
|
||||
return RequestSuccessful()
|
||||
|
||||
async def nh_play(self, message: PlayMessage):
|
||||
# TODO: actually do what's intended to do
|
||||
|
@ -163,7 +164,7 @@ class DiscordBot:
|
|||
for voice_client in self.bot.voice_clients:
|
||||
voice_client: discord.VoiceClient
|
||||
voice_client.play(audio_source)
|
||||
return PlaySuccessful()
|
||||
return RequestError()
|
||||
|
||||
async def run(self):
|
||||
await self.bot.login(self.token)
|
||||
|
|
|
@ -4,7 +4,8 @@ import typing
|
|||
import logging as _logging
|
||||
import sys
|
||||
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 ..database import Alchemy, relationshiplinkchain
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import datetime
|
||||
import dateparser
|
||||
from ..utils import Command, Call, InvalidInputError
|
||||
from ..utils import Command, Call
|
||||
from ..error import InvalidInputError
|
||||
|
||||
|
||||
class DateparserCommand(Command):
|
||||
|
@ -11,9 +12,7 @@ class DateparserCommand(Command):
|
|||
|
||||
@classmethod
|
||||
async def common(cls, call: Call):
|
||||
if len(call.args) == 0:
|
||||
raise InvalidInputError("Missing arg")
|
||||
text = " ".join(call.args)
|
||||
text = call.args.joined(require_at_least=1)
|
||||
date: datetime.datetime = dateparser.parse(text)
|
||||
if date is None:
|
||||
await call.reply("🕕 La data inserita non è valida.")
|
||||
|
|
|
@ -4,7 +4,8 @@ import telegram
|
|||
import typing
|
||||
import os
|
||||
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 ..utils import asyncify
|
||||
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
import traceback
|
||||
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):
|
||||
|
@ -16,13 +23,28 @@ class ErrorHandlerCommand(Command):
|
|||
except InvalidInputError:
|
||||
await call.reply("⚠️ Questo comando non può essere chiamato da solo.")
|
||||
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]")
|
||||
if e_type == NoneFoundError:
|
||||
await call.reply("⚠️ L'elemento richiesto non è stato trovato.")
|
||||
return
|
||||
if e_type == TooManyFoundError:
|
||||
await call.reply("⚠️ La richiesta effettuata è ambigua, pertanto è stata annullata.")
|
||||
return
|
||||
if e_type == UnregisteredError:
|
||||
await call.reply("⚠️ Devi essere registrato a Royalnet per usare questo comando!")
|
||||
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}")
|
||||
formatted_tb: str = '\n'.join(traceback.format_tb(e_tb))
|
||||
call.logger.error(f"Unhandled exception - {e_type.__name__}: {e_value}\n{formatted_tb}")
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import asyncio
|
||||
from ..utils import Command, Call, InvalidInputError
|
||||
from ..utils import Command, Call
|
||||
from royalnet.error import InvalidInputError
|
||||
|
||||
|
||||
class PingCommand(Command):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import typing
|
||||
from ..utils import Command, Call
|
||||
from ..network import Message
|
||||
from ..network import Message, RequestSuccessful, RequestError
|
||||
|
||||
|
||||
class PlayMessage(Message):
|
||||
|
@ -8,15 +8,6 @@ class PlayMessage(Message):
|
|||
self.url: str = url
|
||||
|
||||
|
||||
class PlaySuccessful(Message):
|
||||
pass
|
||||
|
||||
|
||||
class PlayError(Message):
|
||||
def __init__(self, reason: str):
|
||||
self.reason: str = reason
|
||||
|
||||
|
||||
class PlayCommand(Command):
|
||||
command_name = "play"
|
||||
command_description = "Riproduce una canzone in chat vocale."
|
||||
|
@ -25,11 +16,11 @@ class PlayCommand(Command):
|
|||
@classmethod
|
||||
async def common(cls, call: Call):
|
||||
url: str = call.args[0]
|
||||
response: typing.Union[PlaySuccessful, PlayError] = await call.net_request(PlayMessage(url), "discord")
|
||||
if isinstance(response, PlayError):
|
||||
await call.reply(f"⚠️ Si è verificato un'errore nella richiesta di riproduzione:\n[c]{response.reason}[/c]")
|
||||
return
|
||||
elif isinstance(response, PlaySuccessful):
|
||||
response: typing.Union[RequestSuccessful, RequestError] = await call.net_request(PlayMessage(url), "discord")
|
||||
if isinstance(response, RequestSuccessful):
|
||||
await call.reply(f"✅ Richiesta la riproduzione di [c]{url}[/c].")
|
||||
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__}")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import typing
|
||||
import discord
|
||||
from ..utils import Command, Call
|
||||
from ..network import Message
|
||||
from ..network import Message, RequestSuccessful, RequestError
|
||||
|
||||
|
||||
class SummonMessage(Message):
|
||||
|
@ -9,15 +9,6 @@ class SummonMessage(Message):
|
|||
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):
|
||||
|
||||
command_name = "summon"
|
||||
|
@ -27,11 +18,11 @@ class SummonCommand(Command):
|
|||
@classmethod
|
||||
async def common(cls, call: Call):
|
||||
channel_name: str = call.args[0].lstrip("#")
|
||||
response: typing.Union[SummonSuccessful, SummonError] = await call.net_request(SummonMessage(channel_name), "discord")
|
||||
if isinstance(response, SummonError):
|
||||
await call.reply(f"⚠️ Si è verificato un'errore nella richiesta di connessione:\n[c]{response.reason}[/c]")
|
||||
response: typing.Union[RequestSuccessful, RequestError] = await call.net_request(SummonMessage(channel_name), "discord")
|
||||
if isinstance(response, RequestError):
|
||||
await call.reply(f"⚠️ Si è verificato un'errore nella richiesta di connessione:\n[c]{response.exc}[/c]")
|
||||
return
|
||||
elif isinstance(response, SummonSuccessful):
|
||||
elif isinstance(response, RequestSuccessful):
|
||||
await call.reply(f"✅ Mi sono connesso in [c]#{channel_name}[/c].")
|
||||
return
|
||||
raise TypeError(f"Received unexpected response type while summoning the bot: {response.__class__.__name__}")
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import typing
|
||||
from telegram import Update, User
|
||||
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
|
||||
|
||||
|
||||
|
|
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 .royalnetlink import RoyalnetLink, NetworkError, NotConnectedError, NotIdentifiedError
|
||||
from .royalnetserver import RoyalnetServer
|
||||
|
@ -13,4 +13,6 @@ __all__ = ["Message",
|
|||
"NotConnectedError",
|
||||
"NotIdentifiedError",
|
||||
"Package",
|
||||
"RoyalnetServer"]
|
||||
"RoyalnetServer",
|
||||
"RequestSuccessful",
|
||||
"RequestError"]
|
||||
|
|
|
@ -23,3 +23,12 @@ class InvalidPackageEM(ServerErrorMessage):
|
|||
|
||||
class InvalidDestinationEM(InvalidPackageEM):
|
||||
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 pickle
|
||||
import logging as _logging
|
||||
from .messages import Message, ServerErrorMessage
|
||||
from .messages import Message, ServerErrorMessage, RequestError
|
||||
from .packages import Package
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
|
@ -29,7 +29,7 @@ class NetworkError(Exception):
|
|||
class PendingRequest:
|
||||
def __init__(self):
|
||||
self.event: asyncio.Event = asyncio.Event()
|
||||
self.data: Message = None
|
||||
self.data: typing.Optional[Message] = None
|
||||
|
||||
def __repr__(self):
|
||||
if self.event.is_set():
|
||||
|
@ -139,8 +139,11 @@ class RoyalnetLink:
|
|||
# Package is a request
|
||||
assert isinstance(package, Package)
|
||||
log.debug(f"Received request {package.source_conv_id}: {package}")
|
||||
response = await self.request_handler(package.data)
|
||||
if response is not None:
|
||||
response_package: Package = package.reply(response)
|
||||
await self.send(response_package)
|
||||
log.debug(f"Replied to request {response_package.source_conv_id}: {response_package}")
|
||||
try:
|
||||
response = await self.request_handler(package.data)
|
||||
except Exception as exc:
|
||||
response = RequestError(exc=exc)
|
||||
return
|
||||
response_package: Package = package.reply(response)
|
||||
await self.send(response_package)
|
||||
log.debug(f"Replied to request {response_package.source_conv_id}: {response_package}")
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
from .asyncify import asyncify
|
||||
from .call import Call, UnregisteredError
|
||||
from .command import Command, CommandArgs, InvalidInputError, UnsupportedError, InvalidConfigError, ExternalError
|
||||
from .call import Call
|
||||
from .command import Command, CommandArgs
|
||||
from .safeformat import safeformat
|
||||
from .classdictjanitor import cdj
|
||||
from .sleepuntil import sleep_until
|
||||
from .plusformat import plusformat
|
||||
|
||||
__all__ = ["asyncify", "Call", "Command", "safeformat", "InvalidInputError", "UnsupportedError", "CommandArgs",
|
||||
"cdj", "InvalidConfigError", "ExternalError", "sleep_until", "UnregisteredError", "plusformat"]
|
||||
__all__ = ["asyncify", "Call", "Command", "safeformat", "CommandArgs",
|
||||
"cdj", "sleep_until", "plusformat"]
|
||||
|
|
|
@ -10,10 +10,6 @@ if typing.TYPE_CHECKING:
|
|||
loop = asyncio.get_event_loop()
|
||||
|
||||
|
||||
class UnregisteredError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Call:
|
||||
"""A command call. Still an abstract class, subbots should create a new call from this."""
|
||||
|
||||
|
|
|
@ -1,25 +1,12 @@
|
|||
import re
|
||||
import typing
|
||||
|
||||
from royalnet.error import InvalidInputError
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
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):
|
||||
"""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 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:
|
||||
text = " ".join(self)
|
||||
text = self.joined()
|
||||
match = re.match(pattern, text)
|
||||
if match is None:
|
||||
raise InvalidInputError("Pattern didn't match")
|
||||
|
|
Loading…
Reference in a new issue