1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-27 13:34:28 +00:00

Many more improvements

This commit is contained in:
Steffo 2019-04-04 20:18:32 +02:00
parent a564e33efc
commit 6666331a15
16 changed files with 96 additions and 54 deletions

View file

@ -2,6 +2,7 @@ import telegram
import asyncio
import typing
import logging as _logging
import sys
from ..commands import NullCommand
from ..utils import asyncify, Call, Command
from ..network import RoyalnetLink, Message
@ -120,9 +121,17 @@ class TelegramBot:
command = self.missing_command
# Call the command
try:
return await self.Call(message.chat, command, *parameters, update=update).run()
return await self.Call(message.chat, command, parameters,
update=update).run()
except Exception as exc:
return await self.Call(message.chat, self.error_command, *parameters, update=update, exception=exc, previous_command=command).run()
try:
return await self.Call(message.chat, self.error_command, parameters,
update=update,
exception_info=sys.exc_info(),
previous_command=command,
log=log).run()
except Exception as exc2:
log.error(f"Exception in error handler command: {exc2}")
async def handle_net_request(self, message: Message):
pass

View file

@ -8,8 +8,8 @@ class CiaoruoziCommand(Command):
command_title = "Saluta Ruozi, anche se non è più in RYG."
command_syntax = ""
async def telegram(self, call: Call, args: CommandArgs):
update: Update = args.kwargs["update"]
async def telegram(self, call: Call):
update: Update = call.kwargs["update"]
user: User = update.effective_user
if user.id == 112437036:
await call.reply("👋 Ciao me!")

View file

@ -7,7 +7,7 @@ class ColorCommand(Command):
command_title = "Invia un colore in chat...?"
command_syntax = ""
async def common(self, call: Call, args: CommandArgs):
async def common(self, call: Call):
await call.reply("""
[i]I am sorry, unknown error occured during working with your request, Admin were notified[/i]
""")

View file

@ -10,7 +10,7 @@ class DebugAuthorCommand(Command):
require_alchemy_tables = {Royal, Telegram}
async def common(self, call: Call, args: CommandArgs):
async def common(self, call: Call):
author = await call.get_author()
if author is None:
await call.reply(f"☁️ L'autore di questa chiamata è sconosciuto.")

View file

@ -10,10 +10,10 @@ class DebugCreateCommand(Command):
require_alchemy_tables = {Royal, Alias}
async def common(self, call: Call, args: CommandArgs):
royal = call.alchemy.Royal(username=args[0], role="Member")
async def common(self, call: Call):
royal = call.alchemy.Royal(username=call.args[0], role="Member")
call.session.add(royal)
alias = call.alchemy.Alias(royal=royal, alias=royal.username)
call.session.add(alias)
await asyncify(call.session.commit)
await call.reply(f"✅ Utente <code>{royal}</code> creato!")
await call.reply(f"✅ Utente [c]{royal}[/c] creato!")

View file

@ -13,18 +13,28 @@ class DiarioCommand(Command):
require_alchemy_tables = {Royal, Diario, Alias}
async def common(self, call: Call, args: CommandArgs):
async def common(self, call: Call):
# Find the creator of the quotes
creator = await call.get_author()
if creator is None:
await call.reply("⚠️ Devi essere registrato a Royalnet per usare questo comando!")
return
# Recreate the full sentence
text = " ".join(args.args)
raw_text = " ".join(call.args)
# Pass the sentence through the diario regex
match = re.match(r'(!)? *["«‘“‛‟❛❝〝"`]([^"]+)["»’”❜❞〞"`] *(?:(?:-{1,2}|—) *([\w ]+))?(?:, *([^ ].*))?', text)
match = re.match(r'(!)? *["«‘“‛‟❛❝〝"`]([^"]+)["»’”❜❞〞"`] *(?:(?:-{1,2}|—) *([\w ]+))?(?:, *([^ ].*))?', raw_text)
# Find the corresponding matches
if match is None:
raise InvalidInputError("No match found.")
if match is not None:
spoiler = bool(match.group(1))
text = match.group(2)
quoted = match.group(3)
context = match.group(4)
# Otherwise, consider everything part of the text
else:
spoiler = False
text = raw_text
quoted = None
context = None
timestamp = datetime.datetime.now()
# Find if there's a Royalnet account associated with the quoted name
if quoted is not None:
@ -32,8 +42,6 @@ class DiarioCommand(Command):
else:
quoted_alias = None
quoted_account = quoted_alias.royal if quoted_alias is not None else None
# Find the creator of the quotes
creator = await call.get_author()
# Create the diario quote
diario = call.alchemy.Diario(creator=creator,
quoted_account=quoted_account,
@ -45,4 +53,4 @@ class DiarioCommand(Command):
spoiler=spoiler)
call.session.add(diario)
await asyncify(call.session.commit)
await call.reply(f"Aggiunto al diario!")
await call.reply(f"{str(diario)}")

View file

@ -1,5 +1,6 @@
from ..utils import Command, CommandArgs, Call, InvalidInputError
import traceback
from logging import Logger
from ..utils import Command, CommandArgs, Call, InvalidInputError, UnsupportedError
class ErrorHandlerCommand(Command):
@ -7,14 +8,20 @@ class ErrorHandlerCommand(Command):
command_title = "Gestisce gli errori causati dagli altri comandi."
command_syntax = ""
async def telegram(self, call: Call, args: CommandArgs):
async def common(self, call: Call):
raise UnsupportedError()
async def telegram(self, call: Call):
try:
exc = args.kwargs["exception"]
e_type, e_value, e_tb = call.kwargs["exception_info"]
except InvalidInputError:
await call.reply("⚠️ Questo comando non può essere chiamato da solo.")
return
if isinstance(exc, InvalidInputError):
command = args.kwargs["previous_command"]
if e_type == InvalidInputError:
command = call.kwargs["previous_command"]
await call.reply(f"⚠️ Sintassi non valida.\nSintassi corretta:[c]/{command.command_name} {command.command_syntax}[/c]")
return
await call.reply("❌ Eccezione non gestita durante l'esecuzione del comando.")
await call.reply(f"❌ Eccezione non gestita durante l'esecuzione del comando:\n[b]{e_type.__name__}[/b]\n{e_value}")
log: Logger = call.kwargs["log"]
formatted_tb: str = '\n'.join(traceback.format_tb(e_tb))
log.error(f"Unhandled exception - {e_type.__name__}: {e_value}\n{formatted_tb}")

View file

@ -7,5 +7,5 @@ class NullCommand(Command):
command_title = "Non fa nulla."
command_syntax = ""
async def common(self, call: Call, args: CommandArgs):
async def common(self, call: Call):
pass

View file

@ -7,5 +7,5 @@ class PingCommand(Command):
command_title = "Ping pong!"
command_syntax = ""
async def common(self, call: Call, args: CommandArgs):
async def common(self, call: Call):
await call.reply("🏓 Pong!")

View file

@ -11,11 +11,11 @@ class ShipCommand(Command):
command_title = "Crea una ship tra due cose."
command_syntax = "(uno) (due)"
async def common(self, call: Call, args: CommandArgs):
name_one = args[0]
name_two = args[1]
async def common(self, call: Call):
name_one = call.args[0]
name_two = call.args[1]
if name_two == "+":
name_two = args[2]
name_two = call.args[2]
name_one = name_one.lower()
name_two = name_two.lower()
# Get all letters until the first vowel, included

View file

@ -57,6 +57,6 @@ class SmecdsCommand(Command):
command_title = "Secondo me, è colpa dello stagista..."
command_syntax = ""
async def common(self, call: Call, args: CommandArgs):
async def common(self, call: Call):
ds = random.sample(DS_LIST, 1)[0]
return await call.reply(safeformat(SMECDS, ds=ds))

View file

@ -12,17 +12,17 @@ class SyncCommand(Command):
require_alchemy_tables = {Royal, Telegram}
async def common(self, call: Call, args: CommandArgs):
async def common(self, call: Call):
raise UnsupportedError()
async def telegram(self, call: Call, args: CommandArgs):
update: Update = args.kwargs["update"]
async def telegram(self, call: Call):
update: Update = call.kwargs["update"]
# Find the user
user: typing.Optional[User] = update.effective_user
if user is None:
raise ValueError("Trying to sync a None user.")
# Find the Royal
royal = await asyncify(call.session.query(call.alchemy.Royal).filter_by(username=args[0]).one_or_none)
royal = await asyncify(call.session.query(call.alchemy.Royal).filter_by(username=call.args[0]).one_or_none)
if royal is None:
await call.reply("⚠️ Non esiste alcun account Royalnet con quel nome.")
return
@ -46,4 +46,4 @@ class SyncCommand(Command):
telegram.tg_username = user.username
await call.reply(f"✅ Dati di [c]{str(telegram)}[/c] aggiornati.")
# Commit the session
await asyncify(call.session.commit())
await asyncify(call.session.commit)

View file

@ -15,7 +15,7 @@ def relationshiplinkchain(starting_class, ending_class) -> typing.Optional[tuple
if _relationship.mapper in inspected:
continue
result = search(_relationship.mapper, chain + (_relationship,))
if len(result) == 0:
if len(result) != 0:
return result
return ()

View file

@ -1,3 +1,4 @@
import re
from sqlalchemy import Column, \
Integer, \
Text, \
@ -13,7 +14,7 @@ class Diario:
__tablename__ = "diario"
diario_id = Column(Integer, primary_key=True)
creator_id = Column(Integer, ForeignKey("royals.uid"))
creator_id = Column(Integer, ForeignKey("royals.uid"), nullable=False)
quoted_account_id = Column(Integer, ForeignKey("royals.uid"))
quoted = Column(String)
text = Column(Text, nullable=False)
@ -27,3 +28,23 @@ class Diario:
def __repr__(self):
return f"<Diario diario_id={self.diario_id} creator_id={self.creator_id} quoted_account_id={self.quoted_account_id} quoted={self.quoted} text={self.text} context={self.context} timestamp={self.timestamp} media_url={self.media_url} spoiler={self.spoiler}>"
def __str__(self):
# TODO: support media_url
text = f"Riga #{self.diario_id}"
text += f" (salvata da {self.creator.username}"
text += f" alle {self.timestamp.strftime('%Y-%m-%d %H:%M')}):\n"
if self.spoiler:
hidden = re.sub("\w", "", self.text)
text += f"\"{hidden}\"\n"
else:
text += f"[b]\"{self.text}\"[/b]\n"
if self.quoted_account is not None:
text += f"{self.quoted_account.username}"
elif self.quoted is not None:
text += f"{self.quoted}"
else:
text += f" —Anonimo"
if self.context:
text += f", [i]{self.context}[/i]"
return text

View file

@ -32,10 +32,10 @@ class Call:
raise NotImplementedError()
# These parameters / methods should be left alone
def __init__(self, channel, command: Command, *args, **kwargs):
def __init__(self, channel, command: typing.Type[Command], command_args: list, **kwargs):
self.channel = channel
self.command = command
self.args = args
self.args = CommandArgs(command_args)
self.kwargs = kwargs
self.session = None
@ -56,7 +56,7 @@ class Call:
except AttributeError:
coroutine = getattr(self.command, "common")
try:
result = await coroutine(self.command, self, CommandArgs(*self.args, **self.kwargs))
result = await coroutine(self.command, self)
finally:
await self.session_end()
return result

View file

@ -13,23 +13,20 @@ class InvalidInputError(Exception):
pass
class CommandArgs:
class CommandArgs(list):
"""The arguments of a command. Raises InvalidInputError if the requested argument does not exist."""
def __init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
def __getitem__(self, item):
if isinstance(item, int):
try:
return self.args[item]
return super().__getitem__(item)
except IndexError:
raise InvalidInputError(f'Tried to get missing [{item}] arg from CommandArgs')
elif isinstance(item, str):
if isinstance(item, slice):
try:
return self.kwargs[item]
return super().__getitem__(item)
except IndexError:
raise InvalidInputError(f'Tried to get missing ["{item}"] kwarg from CommandArgs')
raise InvalidInputError(f'Tried to get invalid [{item}] slice from CommandArgs')
raise ValueError(f"Invalid type passed to CommandArgs.__getattr__: {type(item)}")
@ -42,5 +39,5 @@ class Command:
require_alchemy_tables: typing.Set = set()
async def common(self, call: "Call", args: CommandArgs):
async def common(self, call: "Call"):
raise NotImplementedError()