mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 19:44:20 +00:00
Create a session for each individual command call
This commit is contained in:
parent
9d1b81d214
commit
251aa1d76a
9 changed files with 95 additions and 83 deletions
|
@ -38,7 +38,7 @@ class DiscordBot(GenericBot):
|
|||
# noinspection PyMethodParameters,PyAbstractClass
|
||||
class DiscordData(CommandData):
|
||||
def __init__(data, interface: CommandInterface, message: discord.Message):
|
||||
data._interface = interface
|
||||
super().__init__(interface)
|
||||
data.message = message
|
||||
|
||||
async def reply(data, text: str):
|
||||
|
|
|
@ -35,6 +35,9 @@ class GenericBot:
|
|||
command = SelectedCommand(interface)
|
||||
except Exception as e:
|
||||
log.error(f"{e.__class__.__qualname__} during the registration of {SelectedCommand.__qualname__}")
|
||||
continue
|
||||
# Linking the command to the interface
|
||||
interface.command = command
|
||||
# Override the main command name, but warn if it's overriding something
|
||||
if f"{interface.prefix}{SelectedCommand.name}" in self.commands:
|
||||
log.warning(f"Overriding (already defined): {SelectedCommand.__qualname__} -> {interface.prefix}{SelectedCommand.name}")
|
||||
|
|
|
@ -55,7 +55,7 @@ class TelegramBot(GenericBot):
|
|||
# noinspection PyMethodParameters,PyAbstractClass
|
||||
class TelegramData(CommandData):
|
||||
def __init__(data, interface: CommandInterface, update: telegram.Update):
|
||||
data.interface = interface
|
||||
super().__init__(interface)
|
||||
data.update = update
|
||||
|
||||
async def reply(data, text: str):
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
import typing
|
||||
import warnings
|
||||
from .commanderrors import UnsupportedError
|
||||
from .commandinterface import CommandInterface
|
||||
|
||||
|
||||
class CommandData:
|
||||
def __init__(self, interface: CommandInterface):
|
||||
self._interface: CommandInterface = interface
|
||||
if len(self._interface.command.tables) > 0:
|
||||
self.session = self._interface.alchemy.Session()
|
||||
else:
|
||||
self.session = None
|
||||
|
||||
async def reply(self, text: str) -> None:
|
||||
"""Send a text message to the channel where the call was made.
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import typing
|
|||
import asyncio
|
||||
from .commanderrors import UnsupportedError
|
||||
if typing.TYPE_CHECKING:
|
||||
from .command import Command
|
||||
from ..database import Alchemy
|
||||
from ..bots import GenericBot
|
||||
|
||||
|
@ -14,10 +15,7 @@ class CommandInterface:
|
|||
loop: asyncio.AbstractEventLoop = NotImplemented
|
||||
|
||||
def __init__(self):
|
||||
if self.alchemy:
|
||||
self.session = self.alchemy.Session()
|
||||
else:
|
||||
self.session = None
|
||||
self.command: typing.Optional[Command] = None # Will be bound after the command has been created
|
||||
|
||||
def register_net_handler(self, message_type: str, network_handler: typing.Callable):
|
||||
"""Register a new handler for messages received through Royalnet."""
|
||||
|
|
|
@ -74,7 +74,7 @@ class DiarioCommand(Command):
|
|||
if not (text or media_url):
|
||||
raise InvalidInputError("Missing text.")
|
||||
# Find the Royalnet account associated with the sender
|
||||
quoted_tg = await asyncify(self.interface.session.query(self.interface.alchemy.Telegram)
|
||||
quoted_tg = await asyncify(data.session.query(self.interface.alchemy.Telegram)
|
||||
.filter_by(tg_id=reply.from_user.id)
|
||||
.one_or_none)
|
||||
quoted_account = quoted_tg.royal if quoted_tg is not None else None
|
||||
|
@ -124,8 +124,8 @@ class DiarioCommand(Command):
|
|||
# Find if there's a Royalnet account associated with the quoted name
|
||||
if quoted is not None:
|
||||
quoted_alias = await asyncify(
|
||||
self.interface.session.query(self.interface.alchemy.Alias)
|
||||
.filter_by(alias=quoted.lower()).one_or_none)
|
||||
data.session.query(self.interface.alchemy.Alias)
|
||||
.filter_by(alias=quoted.lower()).one_or_none)
|
||||
else:
|
||||
quoted_alias = None
|
||||
quoted_account = quoted_alias.royal if quoted_alias is not None else None
|
||||
|
@ -147,8 +147,8 @@ class DiarioCommand(Command):
|
|||
timestamp=timestamp,
|
||||
media_url=media_url,
|
||||
spoiler=spoiler)
|
||||
self.interface.session.add(diario)
|
||||
await asyncify(self.interface.session.commit)
|
||||
data.session.add(diario)
|
||||
await asyncify(data.session.commit)
|
||||
await data.reply(f"✅ {str(diario)}")
|
||||
else:
|
||||
# Find the creator of the quotes
|
||||
|
@ -182,9 +182,9 @@ class DiarioCommand(Command):
|
|||
# Find if there's a Royalnet account associated with the quoted name
|
||||
if quoted is not None:
|
||||
quoted_alias = await asyncify(
|
||||
self.interface.session.query(self.interface.alchemy.Alias)
|
||||
.filter_by(alias=quoted.lower())
|
||||
.one_or_none)
|
||||
data.session.query(self.interface.alchemy.Alias)
|
||||
.filter_by(alias=quoted.lower())
|
||||
.one_or_none)
|
||||
else:
|
||||
quoted_alias = None
|
||||
quoted_account = quoted_alias.royal if quoted_alias is not None else None
|
||||
|
@ -201,6 +201,6 @@ class DiarioCommand(Command):
|
|||
timestamp=timestamp,
|
||||
media_url=None,
|
||||
spoiler=spoiler)
|
||||
self.interface.session.add(diario)
|
||||
await asyncify(self.interface.session.commit)
|
||||
data.session.add(diario)
|
||||
await asyncify(data.session.commit)
|
||||
await data.reply(f"✅ {str(diario)}")
|
||||
|
|
|
@ -9,7 +9,6 @@ from royalnet.commands import *
|
|||
from royalnet.utils import asyncify, telegram_escape, sleep_until
|
||||
from ..tables import MMEvent, MMDecision, MMResponse
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -91,7 +90,7 @@ class MmCommand(Command):
|
|||
text += f"❌ {mmresponse.royal}\n"
|
||||
return text
|
||||
|
||||
async def _run_mm(self, mmevent: MMEvent) -> None:
|
||||
async def _run_mm(self, mmevent: MMEvent, session) -> None:
|
||||
client: telegram.Bot = self.interface.bot.client
|
||||
|
||||
async def update_message() -> None:
|
||||
|
@ -107,61 +106,62 @@ class MmCommand(Command):
|
|||
pass
|
||||
|
||||
decision_string = f"⚫️ Hai detto che forse parteciperai a [b]{mmevent.title}[/b]" \
|
||||
f" alle [b]{mmevent.datetime.strftime('%H:%M')}[/b].\n" \
|
||||
f"Confermi di volerci essere? (Metti sì anche se arrivi un po' in ritardo!)"
|
||||
f" alle [b]{mmevent.datetime.strftime('%H:%M')}[/b].\n" \
|
||||
f"Confermi di volerci essere? (Metti sì anche se arrivi un po' in ritardo!)"
|
||||
|
||||
decision_keyboard = telegram.InlineKeyboardMarkup([
|
||||
[telegram.InlineKeyboardButton("🔵 Ci sarò!", callback_data=f"mm_{mmevent.mmid}_d_YES"),
|
||||
telegram.InlineKeyboardButton("🔴 Non mi interessa più.", callback_data=f"mm_{mmevent.mmid}_d_NO")]
|
||||
])
|
||||
[telegram.InlineKeyboardButton("🔵 Ci sarò!", callback_data=f"mm_{mmevent.mmid}_d_YES"),
|
||||
telegram.InlineKeyboardButton("🔴 Non mi interessa più.", callback_data=f"mm_{mmevent.mmid}_d_NO")]
|
||||
])
|
||||
|
||||
async def decision_yes(data: CommandData):
|
||||
royal = await data.get_author()
|
||||
mmdecision: MMDecision = await asyncify(
|
||||
self.interface.session.query(self.interface.alchemy.MMDecision).filter_by(mmevent=mmevent,
|
||||
royal=royal).one_or_none)
|
||||
data.session.query(self.interface.alchemy.MMDecision).filter_by(mmevent=mmevent,
|
||||
royal=royal).one_or_none)
|
||||
if mmdecision is None:
|
||||
mmdecision: MMDecision = self.interface.alchemy.MMDecision(royal=royal,
|
||||
mmevent=mmevent,
|
||||
decision="YES")
|
||||
self.interface.session.add(mmdecision)
|
||||
data.session.add(mmdecision)
|
||||
else:
|
||||
mmdecision.decision = "YES"
|
||||
await asyncify(self.interface.session.commit)
|
||||
await asyncify(data.session.commit)
|
||||
await update_message()
|
||||
return "🔵 Hai detto che ci sarai!"
|
||||
|
||||
async def decision_maybe(data: CommandData):
|
||||
royal = await data.get_author()
|
||||
mmdecision: MMDecision = await asyncify(
|
||||
self.interface.session.query(self.interface.alchemy.MMDecision).filter_by(mmevent=mmevent,
|
||||
royal=royal).one_or_none)
|
||||
data.session.query(self.interface.alchemy.MMDecision).filter_by(mmevent=mmevent,
|
||||
royal=royal).one_or_none)
|
||||
if mmdecision is None:
|
||||
mmdecision: MMDecision = self.interface.alchemy.MMDecision(royal=royal,
|
||||
mmevent=mmevent,
|
||||
decision="MAYBE")
|
||||
self.interface.session.add(mmdecision)
|
||||
data.session.add(mmdecision)
|
||||
else:
|
||||
mmdecision.decision = "MAYBE"
|
||||
# Can't asyncify this
|
||||
self.interface.session.commit()
|
||||
data.session.commit()
|
||||
await update_message()
|
||||
return f"⚫️ Hai detto che forse ci sarai. Rispondi al messaggio di conferma {self._cycle_duration} minuti prima dell'inizio!"
|
||||
return f"⚫️ Hai detto che forse ci sarai." \
|
||||
f"Rispondi al messaggio di conferma {self._cycle_duration} minuti prima dell'inizio!"
|
||||
|
||||
async def decision_no(data: CommandData):
|
||||
royal = await data.get_author()
|
||||
mmdecision: MMDecision = await asyncify(
|
||||
self.interface.session.query(self.interface.alchemy.MMDecision).filter_by(mmevent=mmevent,
|
||||
royal=royal).one_or_none)
|
||||
data.session.query(self.interface.alchemy.MMDecision).filter_by(mmevent=mmevent,
|
||||
royal=royal).one_or_none)
|
||||
if mmdecision is None:
|
||||
mmdecision: MMDecision = self.interface.alchemy.MMDecision(royal=royal,
|
||||
mmevent=mmevent,
|
||||
decision="NO")
|
||||
self.interface.session.add(mmdecision)
|
||||
data.session.add(mmdecision)
|
||||
else:
|
||||
mmdecision.decision = "NO"
|
||||
# Can't asyncify this
|
||||
self.interface.session.commit()
|
||||
data.session.commit()
|
||||
await update_message()
|
||||
return "🔴 Hai detto che non ti interessa."
|
||||
|
||||
|
@ -169,43 +169,43 @@ class MmCommand(Command):
|
|||
delay = (datetime.datetime.now() - mmevent.datetime).total_seconds()
|
||||
if delay < 60:
|
||||
return f"🚩 E' ora di [b]{mmevent.title}[/b]!\n" \
|
||||
f"Sei pronto?"
|
||||
f"Sei pronto?"
|
||||
return f"🕒 Sei in ritardo di [b]{int(delay / 60)} minuti[/b] per [b]{mmevent.title}[/b]...\n" \
|
||||
f"Sei pronto?"
|
||||
f"Sei pronto?"
|
||||
|
||||
response_keyboard = telegram.InlineKeyboardMarkup([
|
||||
[telegram.InlineKeyboardButton("✅ Ci sono!",
|
||||
callback_data=f"mm_{mmevent.mmid}_r_YES")],
|
||||
[telegram.InlineKeyboardButton("🕒 Aspettatemi ancora un po'!",
|
||||
callback_data=f"mm_{mmevent.mmid}_r_LATER")],
|
||||
[telegram.InlineKeyboardButton("❌ Non vengo più, mi spiace.",
|
||||
callback_data=f"mm_{mmevent.mmid}_r_NO")]
|
||||
])
|
||||
[telegram.InlineKeyboardButton("✅ Ci sono!",
|
||||
callback_data=f"mm_{mmevent.mmid}_r_YES")],
|
||||
[telegram.InlineKeyboardButton("🕒 Aspettatemi ancora un po'!",
|
||||
callback_data=f"mm_{mmevent.mmid}_r_LATER")],
|
||||
[telegram.InlineKeyboardButton("❌ Non vengo più, mi spiace.",
|
||||
callback_data=f"mm_{mmevent.mmid}_r_NO")]
|
||||
])
|
||||
|
||||
async def response_yes(data: CommandData):
|
||||
royal = await data.get_author()
|
||||
mmresponse: MMResponse = await asyncify(
|
||||
self.interface.session.query(self.interface.alchemy.MMResponse).filter_by(mmevent=mmevent,
|
||||
royal=royal).one_or_none)
|
||||
data.session.query(self.interface.alchemy.MMResponse).filter_by(mmevent=mmevent,
|
||||
royal=royal).one_or_none)
|
||||
mmresponse.response = "YES"
|
||||
# Can't asyncify this
|
||||
self.interface.session.commit()
|
||||
data.session.commit()
|
||||
await update_message()
|
||||
return "✅ Sei pronto!"
|
||||
|
||||
def later_string(royal) -> str:
|
||||
return f"🕒 {royal.username} ha chiesto di aspettare {self._cycle_duration} prima di iniziare la" \
|
||||
f" partita.\n\n" \
|
||||
f"Se vuoi iniziare la partita senza aspettarlo, premi Avvia partita su Royal Matchmaking!"
|
||||
f" partita.\n\n" \
|
||||
f"Se vuoi iniziare la partita senza aspettarlo, premi Avvia partita su Royal Matchmaking!"
|
||||
|
||||
async def response_later(data: CommandData):
|
||||
royal = await data.get_author()
|
||||
mmresponse: MMResponse = await asyncify(
|
||||
self.interface.session.query(self.interface.alchemy.MMResponse).filter_by(mmevent=mmevent,
|
||||
royal=royal).one_or_none)
|
||||
data.session.query(self.interface.alchemy.MMResponse).filter_by(mmevent=mmevent,
|
||||
royal=royal).one_or_none)
|
||||
mmresponse.response = "LATER"
|
||||
# Can't asyncify this
|
||||
self.interface.session.commit()
|
||||
data.session.commit()
|
||||
await self.interface.bot.safe_api_call(client.send_message,
|
||||
chat_id=mmevent.creator.telegram[0].tg_id,
|
||||
text=telegram_escape(later_string(royal)),
|
||||
|
@ -217,17 +217,17 @@ class MmCommand(Command):
|
|||
async def response_no(data: CommandData):
|
||||
royal = await data.get_author()
|
||||
mmresponse: MMResponse = await asyncify(
|
||||
self.interface.session.query(self.interface.alchemy.MMResponse).filter_by(mmevent=mmevent,
|
||||
royal=royal).one_or_none)
|
||||
data.session.query(self.interface.alchemy.MMResponse).filter_by(mmevent=mmevent,
|
||||
royal=royal).one_or_none)
|
||||
mmresponse.response = "NO"
|
||||
# Can't asyncify this
|
||||
self.interface.session.commit()
|
||||
data.session.commit()
|
||||
await update_message()
|
||||
return "❌ Hai detto che non ci sarai."
|
||||
|
||||
def started_string():
|
||||
text = f"🚩 L'evento [b]{mmevent.title}[/b] è iniziato!\n\n" \
|
||||
f"Partecipano:\n"
|
||||
f"Partecipano:\n"
|
||||
for mmresponse in sorted(mmevent.responses, key=lambda mmr: mmr.response, reverse=True):
|
||||
if mmresponse.response == "YES":
|
||||
text += f"✅ {mmresponse.royal}\n"
|
||||
|
@ -236,8 +236,8 @@ class MmCommand(Command):
|
|||
return text
|
||||
|
||||
started_without_you_string = f"🚩 Non hai confermato la tua presenza in tempo e [b]{mmevent.title}[/b] è" \
|
||||
f" iniziato senza di te.\n" \
|
||||
f"Mi dispiace!"
|
||||
f" iniziato senza di te.\n" \
|
||||
f"Mi dispiace!"
|
||||
|
||||
async def start_event():
|
||||
mmevent.state = "STARTED"
|
||||
|
@ -259,7 +259,7 @@ class MmCommand(Command):
|
|||
text=telegram_escape(started_without_you_string),
|
||||
parse_mode="HTML",
|
||||
disable_webpage_preview=True)
|
||||
await asyncify(self.interface.session.commit)
|
||||
await asyncify(session.commit)
|
||||
await update_message()
|
||||
|
||||
async def start_key(data: CommandData):
|
||||
|
@ -285,7 +285,7 @@ class MmCommand(Command):
|
|||
parse_mode="HTML",
|
||||
disable_webpage_preview=True,
|
||||
reply_markup=decision_keyboard)
|
||||
await asyncify(self.interface.session.commit)
|
||||
await asyncify(session.commit)
|
||||
await update_message()
|
||||
|
||||
if mmevent.state == "DECISION":
|
||||
|
@ -300,8 +300,8 @@ class MmCommand(Command):
|
|||
mmdecision.decision = "NO"
|
||||
elif mmdecision.decision == "YES":
|
||||
mmresponse: MMResponse = self.interface.alchemy.MMResponse(royal=mmdecision.royal, mmevent=mmevent)
|
||||
self.interface.session.add(mmresponse)
|
||||
await asyncify(self.interface.session.commit)
|
||||
session.add(mmresponse)
|
||||
await asyncify(session.commit)
|
||||
await update_message()
|
||||
|
||||
if mmevent.state == "READY_CHECK":
|
||||
|
@ -347,12 +347,14 @@ class MmCommand(Command):
|
|||
if self.interface.name != "telegram":
|
||||
return
|
||||
log.debug("Loading pending MMEvents from the database")
|
||||
mmevents = self.interface.session.query(self.interface.alchemy.MMEvent) \
|
||||
.filter(self.interface.alchemy.MMEvent.datetime > datetime.datetime.now()) \
|
||||
.all()
|
||||
session = interface.alchemy.Session()
|
||||
mmevents = session.query(self.interface.alchemy.MMEvent) \
|
||||
.filter(self.interface.alchemy.MMEvent.datetime > datetime.datetime.now()) \
|
||||
.all()
|
||||
log.info(f"Found {len(mmevents)} pending MMEvents")
|
||||
for mmevent in mmevents:
|
||||
interface.loop.create_task(self._run_mm(mmevent))
|
||||
session = self.interface.alchemy.Session()
|
||||
interface.loop.create_task(self._run_mm(mmevent, session))
|
||||
|
||||
async def run(self, args: CommandArgs, data: CommandData) -> None:
|
||||
if self.interface.name != "telegram":
|
||||
|
@ -380,18 +382,19 @@ class MmCommand(Command):
|
|||
title=title,
|
||||
description=description,
|
||||
state="WAITING")
|
||||
self.interface.session.add(mmevent)
|
||||
await asyncify(self.interface.session.commit)
|
||||
data.session.add(mmevent)
|
||||
await asyncify(data.session.commit)
|
||||
|
||||
message: telegram.Message = await self.interface.bot.safe_api_call(client.send_message,
|
||||
chat_id=-1001224004974,
|
||||
text=telegram_escape(self._main_text(mmevent)),
|
||||
text=telegram_escape(
|
||||
self._main_text(mmevent)),
|
||||
parse_mode="HTML",
|
||||
disable_webpage_preview=True,
|
||||
reply_markup=self._main_keyboard(mmevent))
|
||||
|
||||
mmevent.message_id = message.message_id
|
||||
# Can't asyncify this
|
||||
await asyncify(self.interface.session.commit)
|
||||
await asyncify(data.session.commit)
|
||||
|
||||
await self._run_mm(mmevent)
|
||||
await self._run_mm(mmevent, data.session)
|
||||
|
|
|
@ -23,13 +23,13 @@ class ReminderCommand(Command):
|
|||
|
||||
def __init__(self, interface: CommandInterface):
|
||||
super().__init__(interface)
|
||||
session = interface.alchemy.Session()
|
||||
reminders = (
|
||||
interface.session
|
||||
.query(interface.alchemy.Reminder)
|
||||
.filter(and_(
|
||||
interface.alchemy.Reminder.datetime >= datetime.datetime.now(),
|
||||
interface.alchemy.Reminder.interface_name == interface.name))
|
||||
.all()
|
||||
session.query(interface.alchemy.Reminder)
|
||||
.filter(and_(
|
||||
interface.alchemy.Reminder.datetime >= datetime.datetime.now(),
|
||||
interface.alchemy.Reminder.interface_name == interface.name))
|
||||
.all()
|
||||
)
|
||||
for reminder in reminders:
|
||||
interface.loop.create_task(self._remind(reminder))
|
||||
|
@ -82,5 +82,5 @@ class ReminderCommand(Command):
|
|||
datetime=date,
|
||||
message=reminder_text)
|
||||
self.interface.loop.create_task(self._remind(reminder))
|
||||
self.interface.session.add(reminder)
|
||||
await asyncify(self.interface.session.commit)
|
||||
data.session.add(reminder)
|
||||
await asyncify(data.session.commit)
|
||||
|
|
|
@ -97,8 +97,8 @@ class TriviaCommand(Command):
|
|||
for answerer in self._answerers[question_id]:
|
||||
if answerer.trivia_score is None:
|
||||
ts = self.interface.alchemy.TriviaScore(royal=answerer)
|
||||
self.interface.session.add(ts)
|
||||
self.interface.session.commit()
|
||||
data.session.add(ts)
|
||||
data.session.commit()
|
||||
if self._answerers[question_id][answerer]:
|
||||
results += self._correct_emoji
|
||||
answerer.trivia_score.correct_answers += 1
|
||||
|
@ -108,4 +108,4 @@ class TriviaCommand(Command):
|
|||
results += f" {answerer} ({answerer.trivia_score.correct_answers}/{answerer.trivia_score.total_answers})\n"
|
||||
await data.reply(results)
|
||||
del self._answerers[question_id]
|
||||
await asyncify(self.interface.session.commit)
|
||||
await asyncify(data.session.commit)
|
||||
|
|
Loading…
Reference in a new issue