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

Create a session for each individual command call

This commit is contained in:
Steffo 2019-10-18 13:05:39 +02:00
parent 9d1b81d214
commit 251aa1d76a
9 changed files with 95 additions and 83 deletions

View file

@ -38,7 +38,7 @@ class DiscordBot(GenericBot):
# noinspection PyMethodParameters,PyAbstractClass # noinspection PyMethodParameters,PyAbstractClass
class DiscordData(CommandData): class DiscordData(CommandData):
def __init__(data, interface: CommandInterface, message: discord.Message): def __init__(data, interface: CommandInterface, message: discord.Message):
data._interface = interface super().__init__(interface)
data.message = message data.message = message
async def reply(data, text: str): async def reply(data, text: str):

View file

@ -35,6 +35,9 @@ class GenericBot:
command = SelectedCommand(interface) command = SelectedCommand(interface)
except Exception as e: except Exception as e:
log.error(f"{e.__class__.__qualname__} during the registration of {SelectedCommand.__qualname__}") 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 # Override the main command name, but warn if it's overriding something
if f"{interface.prefix}{SelectedCommand.name}" in self.commands: if f"{interface.prefix}{SelectedCommand.name}" in self.commands:
log.warning(f"Overriding (already defined): {SelectedCommand.__qualname__} -> {interface.prefix}{SelectedCommand.name}") log.warning(f"Overriding (already defined): {SelectedCommand.__qualname__} -> {interface.prefix}{SelectedCommand.name}")

View file

@ -55,7 +55,7 @@ class TelegramBot(GenericBot):
# noinspection PyMethodParameters,PyAbstractClass # noinspection PyMethodParameters,PyAbstractClass
class TelegramData(CommandData): class TelegramData(CommandData):
def __init__(data, interface: CommandInterface, update: telegram.Update): def __init__(data, interface: CommandInterface, update: telegram.Update):
data.interface = interface super().__init__(interface)
data.update = update data.update = update
async def reply(data, text: str): async def reply(data, text: str):

View file

@ -1,9 +1,17 @@
import typing import typing
import warnings import warnings
from .commanderrors import UnsupportedError from .commanderrors import UnsupportedError
from .commandinterface import CommandInterface
class CommandData: 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: async def reply(self, text: str) -> None:
"""Send a text message to the channel where the call was made. """Send a text message to the channel where the call was made.

View file

@ -2,6 +2,7 @@ import typing
import asyncio import asyncio
from .commanderrors import UnsupportedError from .commanderrors import UnsupportedError
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
from .command import Command
from ..database import Alchemy from ..database import Alchemy
from ..bots import GenericBot from ..bots import GenericBot
@ -14,10 +15,7 @@ class CommandInterface:
loop: asyncio.AbstractEventLoop = NotImplemented loop: asyncio.AbstractEventLoop = NotImplemented
def __init__(self): def __init__(self):
if self.alchemy: self.command: typing.Optional[Command] = None # Will be bound after the command has been created
self.session = self.alchemy.Session()
else:
self.session = None
def register_net_handler(self, message_type: str, network_handler: typing.Callable): def register_net_handler(self, message_type: str, network_handler: typing.Callable):
"""Register a new handler for messages received through Royalnet.""" """Register a new handler for messages received through Royalnet."""

View file

@ -74,7 +74,7 @@ class DiarioCommand(Command):
if not (text or media_url): if not (text or media_url):
raise InvalidInputError("Missing text.") raise InvalidInputError("Missing text.")
# Find the Royalnet account associated with the sender # 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) .filter_by(tg_id=reply.from_user.id)
.one_or_none) .one_or_none)
quoted_account = quoted_tg.royal if quoted_tg is not None else None quoted_account = quoted_tg.royal if quoted_tg is not None else None
@ -124,7 +124,7 @@ class DiarioCommand(Command):
# Find if there's a Royalnet account associated with the quoted name # Find if there's a Royalnet account associated with the quoted name
if quoted is not None: if quoted is not None:
quoted_alias = await asyncify( quoted_alias = await asyncify(
self.interface.session.query(self.interface.alchemy.Alias) data.session.query(self.interface.alchemy.Alias)
.filter_by(alias=quoted.lower()).one_or_none) .filter_by(alias=quoted.lower()).one_or_none)
else: else:
quoted_alias = None quoted_alias = None
@ -147,8 +147,8 @@ class DiarioCommand(Command):
timestamp=timestamp, timestamp=timestamp,
media_url=media_url, media_url=media_url,
spoiler=spoiler) spoiler=spoiler)
self.interface.session.add(diario) data.session.add(diario)
await asyncify(self.interface.session.commit) await asyncify(data.session.commit)
await data.reply(f"{str(diario)}") await data.reply(f"{str(diario)}")
else: else:
# Find the creator of the quotes # Find the creator of the quotes
@ -182,7 +182,7 @@ class DiarioCommand(Command):
# Find if there's a Royalnet account associated with the quoted name # Find if there's a Royalnet account associated with the quoted name
if quoted is not None: if quoted is not None:
quoted_alias = await asyncify( quoted_alias = await asyncify(
self.interface.session.query(self.interface.alchemy.Alias) data.session.query(self.interface.alchemy.Alias)
.filter_by(alias=quoted.lower()) .filter_by(alias=quoted.lower())
.one_or_none) .one_or_none)
else: else:
@ -201,6 +201,6 @@ class DiarioCommand(Command):
timestamp=timestamp, timestamp=timestamp,
media_url=None, media_url=None,
spoiler=spoiler) spoiler=spoiler)
self.interface.session.add(diario) data.session.add(diario)
await asyncify(self.interface.session.commit) await asyncify(data.session.commit)
await data.reply(f"{str(diario)}") await data.reply(f"{str(diario)}")

View file

@ -9,7 +9,6 @@ from royalnet.commands import *
from royalnet.utils import asyncify, telegram_escape, sleep_until from royalnet.utils import asyncify, telegram_escape, sleep_until
from ..tables import MMEvent, MMDecision, MMResponse from ..tables import MMEvent, MMDecision, MMResponse
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -91,7 +90,7 @@ class MmCommand(Command):
text += f"{mmresponse.royal}\n" text += f"{mmresponse.royal}\n"
return text 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 client: telegram.Bot = self.interface.bot.client
async def update_message() -> None: async def update_message() -> None:
@ -118,50 +117,51 @@ class MmCommand(Command):
async def decision_yes(data: CommandData): async def decision_yes(data: CommandData):
royal = await data.get_author() royal = await data.get_author()
mmdecision: MMDecision = await asyncify( mmdecision: MMDecision = await asyncify(
self.interface.session.query(self.interface.alchemy.MMDecision).filter_by(mmevent=mmevent, data.session.query(self.interface.alchemy.MMDecision).filter_by(mmevent=mmevent,
royal=royal).one_or_none) royal=royal).one_or_none)
if mmdecision is None: if mmdecision is None:
mmdecision: MMDecision = self.interface.alchemy.MMDecision(royal=royal, mmdecision: MMDecision = self.interface.alchemy.MMDecision(royal=royal,
mmevent=mmevent, mmevent=mmevent,
decision="YES") decision="YES")
self.interface.session.add(mmdecision) data.session.add(mmdecision)
else: else:
mmdecision.decision = "YES" mmdecision.decision = "YES"
await asyncify(self.interface.session.commit) await asyncify(data.session.commit)
await update_message() await update_message()
return "🔵 Hai detto che ci sarai!" return "🔵 Hai detto che ci sarai!"
async def decision_maybe(data: CommandData): async def decision_maybe(data: CommandData):
royal = await data.get_author() royal = await data.get_author()
mmdecision: MMDecision = await asyncify( mmdecision: MMDecision = await asyncify(
self.interface.session.query(self.interface.alchemy.MMDecision).filter_by(mmevent=mmevent, data.session.query(self.interface.alchemy.MMDecision).filter_by(mmevent=mmevent,
royal=royal).one_or_none) royal=royal).one_or_none)
if mmdecision is None: if mmdecision is None:
mmdecision: MMDecision = self.interface.alchemy.MMDecision(royal=royal, mmdecision: MMDecision = self.interface.alchemy.MMDecision(royal=royal,
mmevent=mmevent, mmevent=mmevent,
decision="MAYBE") decision="MAYBE")
self.interface.session.add(mmdecision) data.session.add(mmdecision)
else: else:
mmdecision.decision = "MAYBE" mmdecision.decision = "MAYBE"
# Can't asyncify this # Can't asyncify this
self.interface.session.commit() data.session.commit()
await update_message() 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): async def decision_no(data: CommandData):
royal = await data.get_author() royal = await data.get_author()
mmdecision: MMDecision = await asyncify( mmdecision: MMDecision = await asyncify(
self.interface.session.query(self.interface.alchemy.MMDecision).filter_by(mmevent=mmevent, data.session.query(self.interface.alchemy.MMDecision).filter_by(mmevent=mmevent,
royal=royal).one_or_none) royal=royal).one_or_none)
if mmdecision is None: if mmdecision is None:
mmdecision: MMDecision = self.interface.alchemy.MMDecision(royal=royal, mmdecision: MMDecision = self.interface.alchemy.MMDecision(royal=royal,
mmevent=mmevent, mmevent=mmevent,
decision="NO") decision="NO")
self.interface.session.add(mmdecision) data.session.add(mmdecision)
else: else:
mmdecision.decision = "NO" mmdecision.decision = "NO"
# Can't asyncify this # Can't asyncify this
self.interface.session.commit() data.session.commit()
await update_message() await update_message()
return "🔴 Hai detto che non ti interessa." return "🔴 Hai detto che non ti interessa."
@ -185,11 +185,11 @@ class MmCommand(Command):
async def response_yes(data: CommandData): async def response_yes(data: CommandData):
royal = await data.get_author() royal = await data.get_author()
mmresponse: MMResponse = await asyncify( mmresponse: MMResponse = await asyncify(
self.interface.session.query(self.interface.alchemy.MMResponse).filter_by(mmevent=mmevent, data.session.query(self.interface.alchemy.MMResponse).filter_by(mmevent=mmevent,
royal=royal).one_or_none) royal=royal).one_or_none)
mmresponse.response = "YES" mmresponse.response = "YES"
# Can't asyncify this # Can't asyncify this
self.interface.session.commit() data.session.commit()
await update_message() await update_message()
return "✅ Sei pronto!" return "✅ Sei pronto!"
@ -201,11 +201,11 @@ class MmCommand(Command):
async def response_later(data: CommandData): async def response_later(data: CommandData):
royal = await data.get_author() royal = await data.get_author()
mmresponse: MMResponse = await asyncify( mmresponse: MMResponse = await asyncify(
self.interface.session.query(self.interface.alchemy.MMResponse).filter_by(mmevent=mmevent, data.session.query(self.interface.alchemy.MMResponse).filter_by(mmevent=mmevent,
royal=royal).one_or_none) royal=royal).one_or_none)
mmresponse.response = "LATER" mmresponse.response = "LATER"
# Can't asyncify this # Can't asyncify this
self.interface.session.commit() data.session.commit()
await self.interface.bot.safe_api_call(client.send_message, await self.interface.bot.safe_api_call(client.send_message,
chat_id=mmevent.creator.telegram[0].tg_id, chat_id=mmevent.creator.telegram[0].tg_id,
text=telegram_escape(later_string(royal)), text=telegram_escape(later_string(royal)),
@ -217,11 +217,11 @@ class MmCommand(Command):
async def response_no(data: CommandData): async def response_no(data: CommandData):
royal = await data.get_author() royal = await data.get_author()
mmresponse: MMResponse = await asyncify( mmresponse: MMResponse = await asyncify(
self.interface.session.query(self.interface.alchemy.MMResponse).filter_by(mmevent=mmevent, data.session.query(self.interface.alchemy.MMResponse).filter_by(mmevent=mmevent,
royal=royal).one_or_none) royal=royal).one_or_none)
mmresponse.response = "NO" mmresponse.response = "NO"
# Can't asyncify this # Can't asyncify this
self.interface.session.commit() data.session.commit()
await update_message() await update_message()
return "❌ Hai detto che non ci sarai." return "❌ Hai detto che non ci sarai."
@ -259,7 +259,7 @@ class MmCommand(Command):
text=telegram_escape(started_without_you_string), text=telegram_escape(started_without_you_string),
parse_mode="HTML", parse_mode="HTML",
disable_webpage_preview=True) disable_webpage_preview=True)
await asyncify(self.interface.session.commit) await asyncify(session.commit)
await update_message() await update_message()
async def start_key(data: CommandData): async def start_key(data: CommandData):
@ -285,7 +285,7 @@ class MmCommand(Command):
parse_mode="HTML", parse_mode="HTML",
disable_webpage_preview=True, disable_webpage_preview=True,
reply_markup=decision_keyboard) reply_markup=decision_keyboard)
await asyncify(self.interface.session.commit) await asyncify(session.commit)
await update_message() await update_message()
if mmevent.state == "DECISION": if mmevent.state == "DECISION":
@ -300,8 +300,8 @@ class MmCommand(Command):
mmdecision.decision = "NO" mmdecision.decision = "NO"
elif mmdecision.decision == "YES": elif mmdecision.decision == "YES":
mmresponse: MMResponse = self.interface.alchemy.MMResponse(royal=mmdecision.royal, mmevent=mmevent) mmresponse: MMResponse = self.interface.alchemy.MMResponse(royal=mmdecision.royal, mmevent=mmevent)
self.interface.session.add(mmresponse) session.add(mmresponse)
await asyncify(self.interface.session.commit) await asyncify(session.commit)
await update_message() await update_message()
if mmevent.state == "READY_CHECK": if mmevent.state == "READY_CHECK":
@ -347,12 +347,14 @@ class MmCommand(Command):
if self.interface.name != "telegram": if self.interface.name != "telegram":
return return
log.debug("Loading pending MMEvents from the database") log.debug("Loading pending MMEvents from the database")
mmevents = self.interface.session.query(self.interface.alchemy.MMEvent) \ session = interface.alchemy.Session()
mmevents = session.query(self.interface.alchemy.MMEvent) \
.filter(self.interface.alchemy.MMEvent.datetime > datetime.datetime.now()) \ .filter(self.interface.alchemy.MMEvent.datetime > datetime.datetime.now()) \
.all() .all()
log.info(f"Found {len(mmevents)} pending MMEvents") log.info(f"Found {len(mmevents)} pending MMEvents")
for mmevent in 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: async def run(self, args: CommandArgs, data: CommandData) -> None:
if self.interface.name != "telegram": if self.interface.name != "telegram":
@ -380,18 +382,19 @@ class MmCommand(Command):
title=title, title=title,
description=description, description=description,
state="WAITING") state="WAITING")
self.interface.session.add(mmevent) data.session.add(mmevent)
await asyncify(self.interface.session.commit) await asyncify(data.session.commit)
message: telegram.Message = await self.interface.bot.safe_api_call(client.send_message, message: telegram.Message = await self.interface.bot.safe_api_call(client.send_message,
chat_id=-1001224004974, chat_id=-1001224004974,
text=telegram_escape(self._main_text(mmevent)), text=telegram_escape(
self._main_text(mmevent)),
parse_mode="HTML", parse_mode="HTML",
disable_webpage_preview=True, disable_webpage_preview=True,
reply_markup=self._main_keyboard(mmevent)) reply_markup=self._main_keyboard(mmevent))
mmevent.message_id = message.message_id mmevent.message_id = message.message_id
# Can't asyncify this # 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)

View file

@ -23,9 +23,9 @@ class ReminderCommand(Command):
def __init__(self, interface: CommandInterface): def __init__(self, interface: CommandInterface):
super().__init__(interface) super().__init__(interface)
session = interface.alchemy.Session()
reminders = ( reminders = (
interface.session session.query(interface.alchemy.Reminder)
.query(interface.alchemy.Reminder)
.filter(and_( .filter(and_(
interface.alchemy.Reminder.datetime >= datetime.datetime.now(), interface.alchemy.Reminder.datetime >= datetime.datetime.now(),
interface.alchemy.Reminder.interface_name == interface.name)) interface.alchemy.Reminder.interface_name == interface.name))
@ -82,5 +82,5 @@ class ReminderCommand(Command):
datetime=date, datetime=date,
message=reminder_text) message=reminder_text)
self.interface.loop.create_task(self._remind(reminder)) self.interface.loop.create_task(self._remind(reminder))
self.interface.session.add(reminder) data.session.add(reminder)
await asyncify(self.interface.session.commit) await asyncify(data.session.commit)

View file

@ -97,8 +97,8 @@ class TriviaCommand(Command):
for answerer in self._answerers[question_id]: for answerer in self._answerers[question_id]:
if answerer.trivia_score is None: if answerer.trivia_score is None:
ts = self.interface.alchemy.TriviaScore(royal=answerer) ts = self.interface.alchemy.TriviaScore(royal=answerer)
self.interface.session.add(ts) data.session.add(ts)
self.interface.session.commit() data.session.commit()
if self._answerers[question_id][answerer]: if self._answerers[question_id][answerer]:
results += self._correct_emoji results += self._correct_emoji
answerer.trivia_score.correct_answers += 1 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" results += f" {answerer} ({answerer.trivia_score.correct_answers}/{answerer.trivia_score.total_answers})\n"
await data.reply(results) await data.reply(results)
del self._answerers[question_id] del self._answerers[question_id]
await asyncify(self.interface.session.commit) await asyncify(data.session.commit)