1
Fork 0
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:
Steffo 2019-04-16 17:02:50 +02:00
parent 85468ec78d
commit 90f566107f
18 changed files with 121 additions and 88 deletions

5
.gitignore vendored
View file

@ -2,10 +2,7 @@ config.ini
.idea/
.vscode/
__pycache__
diario.json
libopus-0.dll
music.opus
opusfiles/
downloads/
ignored/
markovmodels/
logs/

View file

@ -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"]

View file

@ -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)

View file

@ -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

View file

@ -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.")

View file

@ -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

View file

@ -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}")

View file

@ -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):

View file

@ -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__}")

View file

@ -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__}")

View file

@ -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
View 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."""

View file

@ -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"]

View file

@ -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

View file

@ -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}")

View file

@ -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"]

View file

@ -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."""

View file

@ -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")