1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-23 19:44:20 +00:00

Progress on mm

This commit is contained in:
Steffo 2019-10-26 02:46:56 +02:00
parent c7ebfe3622
commit add6170183
21 changed files with 189 additions and 475 deletions

View file

@ -11,7 +11,7 @@ from .videochannel import VideochannelCommand
from .dnditem import DnditemCommand from .dnditem import DnditemCommand
from .dndspell import DndspellCommand from .dndspell import DndspellCommand
from .trivia import TriviaCommand from .trivia import TriviaCommand
from .mm import MmCommand from .matchmaking import MmCommand
from .pause import PauseCommand from .pause import PauseCommand
from .play import PlayCommand from .play import PlayCommand
from .playmode import PlaymodeCommand from .playmode import PlaymodeCommand

View file

@ -10,7 +10,7 @@ class CvCommand(Command):
description: str = "Elenca le persone attualmente connesse alla chat vocale." description: str = "Elenca le persone attualmente connesse alla chat vocale."
syntax: str = "[guildname] ['all']" syntax: str = "[guildname] [all]"
@staticmethod @staticmethod
async def _legacy_cv_handler(bot: DiscordBot, guild_name: typing.Optional[str], everyone: bool): async def _legacy_cv_handler(bot: DiscordBot, guild_name: typing.Optional[str], everyone: bool):

View file

@ -33,7 +33,7 @@ class DiarioCommand(Command):
description: str = "Aggiungi una citazione al Diario." description: str = "Aggiungi una citazione al Diario."
syntax = "[!] \"(testo)\" --[autore], [contesto]" syntax = "[!] \"{testo}\" --[autore], [contesto]"
tables = {User, Diario, Alias} tables = {User, Diario, Alias}

View file

@ -12,7 +12,7 @@ class DnditemCommand(Command):
description: str = "Ottieni informazioni su un oggetto di D&D5e." description: str = "Ottieni informazioni su un oggetto di D&D5e."
syntax = "(nomeoggetto)" syntax = "{nomeoggetto}"
_dnddata: sortedcontainers.SortedKeyList = None _dnddata: sortedcontainers.SortedKeyList = None

View file

@ -12,7 +12,7 @@ class DndspellCommand(Command):
description: str = "Ottieni informazioni su una magia di D&D5e." description: str = "Ottieni informazioni su una magia di D&D5e."
syntax = "(nomemagia)" syntax = "{nomemagia}"
_dnddata: sortedcontainers.SortedKeyList = None _dnddata: sortedcontainers.SortedKeyList = None

View file

@ -0,0 +1,129 @@
import pickle
from telegram import Bot as PTBBot
from telegram import Message as PTBMessage
from telegram.error import BadRequest
from telegram import InlineKeyboardMarkup as IKM
from telegram import InlineKeyboardButton as IKB
from royalnet.commands import *
from royalnet.bots import TelegramBot
from royalnet.utils import telegram_escape, asyncify
from ..tables import MMEvent, MMResponse
from ..utils import MMChoice, MMInterfaceData, MMInterfaceDataTelegram
class MatchmakingCommand(Command):
name: str = "matchmaking"
description: str = "Cerca persone per una partita a qualcosa!"
syntax: str = "[ {ora} ] {nome}\n[descrizione]"
aliases = ["mm", "lfg"]
tables = {MMEvent, MMResponse}
def __init__(self, interface: CommandInterface):
super().__init__(interface)
# Find all relevant MMEvents and run them
...
async def run(self, args: CommandArgs, data: CommandData) -> None:
# Create a new MMEvent and run it
...
_mm_chat_id = -1001224004974
def _gen_mm_message(self, mmevent: MMEvent) -> str:
text = f"🌐 [{mmevent.datetime.strftime('%Y-%m-%d %H:%M')}] [b]{mmevent.title}[/b]\n"
if mmevent.description:
text += f"{mmevent.description}\n"
text += "\n"
for response in mmevent.responses:
response: MMResponse
text += f"{response.choice.value} {response.royal}\n"
return text
def _gen_telegram_keyboard(self, mmevent: MMEvent):
return IKM([
[IKB(f"{MMChoice.YES.value} Ci sarò!", callback_data=f"mm{mmevent.mmid}_YES")],
[IKB(f"{MMChoice.MAYBE.value} (Forse.)", callback_data=f"mm{mmevent.mmid}_MAYBE")],
[IKB(f"{MMChoice.LATE_SHORT.value} Arrivo dopo 5-10 min.", callback_data=f"mm{mmevent.mmid}_LATE_SHORT")],
[IKB(f"{MMChoice.LATE_MEDIUM.value} Arrivo dopo 15-35 min.", callback_data=f"mm{mmevent.mmid}_LATE_MEDIUM")],
[IKB(f"{MMChoice.LATE_LONG.value} Arrivo dopo 40+ min.", callback_data=f"mm{mmevent.mmid}_LATE_LONG")],
[IKB(f"{MMChoice.NO_TIME} Non posso a quell'ora...", callback_data=f"mm{mmevent.mmid}_NO_TIME")],
[IKB(f"{MMChoice.NO_INTEREST} Non mi interessa.", callback_data=f"mm{mmevent.mmid}_NO_INTEREST")],
[IKB(f"{MMChoice.NO_TECH} Ho un problema!", callback_data=f"mm{mmevent.mmid}_NO_TECH")],
])
async def _update_telegram_mm_message(self, client: PTBBot, mmevent: MMEvent):
try:
await self.interface.bot.safe_api_call(client.edit_message_text,
chat_id=self._mm_chat_id,
text=telegram_escape(self._gen_mm_message(mmevent)),
message_id=mmevent.interface_data,
parse_mode="HTML",
disable_web_page_preview=True,
reply_markup=self._gen_telegram_keyboard(mmevent))
except BadRequest:
pass
def _gen_mm_telegram_callback(self, client: PTBBot, mmid: int, choice: MMChoice):
async def callback(data: CommandData):
author = await data.get_author(error_if_none=True)
# Find the MMEvent with the current session
mmevent: MMEvent = await asyncify(data.session.query(self.alchemy.MMEvent).get, mmid)
mmresponse: MMResponse = await asyncify(data.session.query(self.alchemy.MMResponse).filter_by(royal=author, mmevent=mmevent).one_or_none)
if mmresponse is None:
mmresponse = self.alchemy.MMResponse(royal=author, mmevent=mmevent, choice=choice)
data.session.add(mmresponse)
else:
mmresponse.choice = choice
await data.session_commit()
await self._update_telegram_mm_message(client, mmevent)
return f"✅ Messaggio ricevuto!"
return callback
async def _run_mmevent(self, mmid: int):
"""Run a MMEvent."""
# Open a new Alchemy Session
session = self.alchemy.Session()
# Find the MMEvent with the current session
mmevent: MMEvent = await asyncify(session.query(self.alchemy.MMEvent).get, mmid)
if mmevent is None:
raise ValueError("Invalid mmid.")
# Ensure the MMEvent interface matches the current one
if mmevent.interface != self.interface.name:
raise ValueError("Invalid interface.")
# If the matchmaking message hasn't been sent yet, do so now
if mmevent.interface_data is None:
if self.interface.name == "telegram":
bot: TelegramBot = self.interface.bot
client: PTBBot = bot.client
# Build the Telegram keyboard
# Send the keyboard
message: PTBMessage = await self.interface.bot.safe_api_call(client.send_message,
chat_id=self._mm_chat_id,
text=telegram_escape(self._gen_mm_message(mmevent)),
parse_mode="HTML",
disable_webpage_preview=True,
reply_markup=self._gen_telegram_keyboard(mmevent.mmid))
# Store message data in the interface data object
mmevent.interface_data = MMInterfaceDataTelegram(chat_id=self._mm_chat_id, message_id=message.message_id)
else:
raise UnsupportedError()
# Register handlers for the keyboard events
if self.interface.name == "telegram":
bot: TelegramBot = self.interface.bot
client: PTBBot = bot.client
self.interface.register_keyboard_key(f"mm{mmevent.mmid}_YES", callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.YES))
self.interface.register_keyboard_key(f"mm{mmevent.mmid}_MAYBE", callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.MAYBE))
self.interface.register_keyboard_key(f"mm{mmevent.mmid}_LATE_SHORT", callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.LATE_SHORT))
self.interface.register_keyboard_key(f"mm{mmevent.mmid}_LATE_MEDIUM", callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.LATE_MEDIUM))
self.interface.register_keyboard_key(f"mm{mmevent.mmid}_LATE_LONG", callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.LATE_LONG))
self.interface.register_keyboard_key(f"mm{mmevent.mmid}_NO_TIME", callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.NO_TIME))
self.interface.register_keyboard_key(f"mm{mmevent.mmid}_NO_INTEREST", callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.NO_INTEREST))
self.interface.register_keyboard_key(f"mm{mmevent.mmid}_NO_TECH", callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.NO_TECH))
else:
raise UnsupportedError()
# Sleep until the time of the event
...

View file

@ -1,404 +0,0 @@
import datetime
import dateparser
import telegram
import asyncio
import re
import logging
import typing
from royalnet.commands import *
from royalnet.utils import asyncify, telegram_escape, sleep_until
from ..tables import MMEvent, MMDecision, MMResponse
log = logging.getLogger(__name__)
class MmCommand(Command):
"""Matchmaking command.
Requires the MM_CHANNEL_ID envvar to be set."""
name: str = "mm"
aliases = ["matchmaking", "matchmake", "lfg", "lookingforgroup"]
description: str = "Trova giocatori per una partita a qualcosa."
syntax: str = "[ (data) ] (nomegioco)\n[descrizione]"
tables = {MMEvent, MMDecision, MMResponse}
_cycle_duration = 10
@staticmethod
def _main_keyboard(mmevent: MMEvent) -> typing.Optional[telegram.InlineKeyboardMarkup]:
if mmevent.state == "WAITING":
return telegram.InlineKeyboardMarkup([
[telegram.InlineKeyboardButton("🔵 Ci sarò!", callback_data=f"mm_{mmevent.mmid}_d_YES")],
[telegram.InlineKeyboardButton("⚫️ Forse...", callback_data=f"mm_{mmevent.mmid}_d_MAYBE")],
[telegram.InlineKeyboardButton("🔴 Non mi interessa.", callback_data=f"mm_{mmevent.mmid}_d_NO")]
])
elif mmevent.state == "DECISION":
return telegram.InlineKeyboardMarkup([
[telegram.InlineKeyboardButton("🔵 Ci sarò!", callback_data=f"mm_{mmevent.mmid}_d_YES"),
telegram.InlineKeyboardButton("🔴 Non mi interessa...", callback_data=f"mm_{mmevent.mmid}_d_NO")]
])
elif mmevent.state == "READY_CHECK":
return telegram.InlineKeyboardMarkup([
[telegram.InlineKeyboardButton("🚩 Avvia la partita", callback_data=f"mm_{mmevent.mmid}_start")]
])
elif mmevent.state == "STARTED":
return None
else:
raise ValueError(f"state is of an unknown value ({mmevent.state})")
@staticmethod
def _main_text(mmevent: MMEvent):
text = f"🌐 [{mmevent.datetime.strftime('%Y-%m-%d %H:%M')}] [b]{mmevent.title}[/b]\n"
if mmevent.description:
text += f"{mmevent.description}\n"
text += "\n"
if mmevent.state == "WAITING" or mmevent.state == "DECISION":
for mmdecision in sorted(mmevent.decisions, key=lambda mmd: mmd.royal.username):
mmdecision: "MMDecision"
if mmdecision.decision == "YES":
text += "🔵 "
elif mmdecision.decision == "MAYBE":
text += "⚫️ "
elif mmdecision.decision == "NO":
text += "🔴 "
else:
raise ValueError(f"decision is of an unknown value ({mmdecision.decision})")
text += f"{mmdecision.royal}\n"
elif mmevent.state == "READY_CHECK":
for mmresponse in sorted(mmevent.responses, key=lambda mmr: mmr.royal.username):
mmresponse: "MMResponse"
if mmresponse.response is None:
text += ""
elif mmresponse.response == "YES":
text += ""
elif mmresponse.response == "LATER":
text += "🕒 "
elif mmresponse.response == "NO":
text += ""
else:
raise ValueError(f"response is of an unknown value ({mmresponse.response})")
text += f"{mmresponse.royal}\n"
elif mmevent.state == "STARTED":
for mmresponse in sorted(mmevent.responses, key=lambda mmr: mmr.response, reverse=True):
if mmresponse.response == "YES":
text += f"{mmresponse.royal}\n"
elif mmresponse.response == "NO":
text += f"{mmresponse.royal}\n"
return text
async def _run_mm(self, mmevent: MMEvent, session) -> None:
client: telegram.Bot = self.interface.bot.client
async def update_message() -> None:
try:
await self.interface.bot.safe_api_call(client.edit_message_text,
text=telegram_escape(self._main_text(mmevent)),
chat_id=-1001224004974,
message_id=mmevent.message_id,
parse_mode="HTML",
disable_web_page_preview=True,
reply_markup=self._main_keyboard(mmevent))
except telegram.error.BadRequest:
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!)"
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")]
])
async def decision_yes(data: CommandData):
royal = await data.get_author()
mmdecision: MMDecision = await asyncify(
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")
session.add(mmdecision)
else:
mmdecision.decision = "YES"
await asyncify(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(
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")
session.add(mmdecision)
else:
mmdecision.decision = "MAYBE"
# Can't asyncify this
session.commit()
await update_message()
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(
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")
session.add(mmdecision)
else:
mmdecision.decision = "NO"
# Can't asyncify this
session.commit()
await update_message()
return "🔴 Hai detto che non ti interessa."
def response_string() -> str:
delay = (datetime.datetime.now() - mmevent.datetime).total_seconds()
if delay < 60:
return f"🚩 E' ora di [b]{mmevent.title}[/b]!\n" \
f"Sei pronto?"
return f"🕒 Sei in ritardo di [b]{int(delay / 60)} minuti[/b] per [b]{mmevent.title}[/b]...\n" \
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")]
])
async def response_yes(data: CommandData):
royal = await data.get_author()
mmresponse: MMResponse = await asyncify(
session.query(self.interface.alchemy.MMResponse).filter_by(mmevent=mmevent,
royal=royal).one_or_none)
mmresponse.response = "YES"
# Can't asyncify this
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!"
async def response_later(data: CommandData):
royal = await data.get_author()
mmresponse: MMResponse = await asyncify(
session.query(self.interface.alchemy.MMResponse).filter_by(mmevent=mmevent,
royal=royal).one_or_none)
mmresponse.response = "LATER"
# Can't asyncify this
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)),
parse_mode="HTML",
disable_webpage_preview=True)
await update_message()
return f"🕒 Hai chiesto agli altri di aspettarti {self._cycle_duration} minuti."
async def response_no(data: CommandData):
royal = await data.get_author()
mmresponse: MMResponse = await asyncify(
session.query(self.interface.alchemy.MMResponse).filter_by(mmevent=mmevent,
royal=royal).one_or_none)
mmresponse.response = "NO"
# Can't asyncify this
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"
for mmresponse in sorted(mmevent.responses, key=lambda mmr: mmr.response, reverse=True):
if mmresponse.response == "YES":
text += f"{mmresponse.royal}\n"
elif mmresponse.response == "NO":
text += f"{mmresponse.royal}\n"
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!"
async def start_event():
mmevent.state = "STARTED"
for mmresponse in mmevent.responses:
if mmresponse.response is None:
mmresponse.response = "NO"
if mmresponse.response == "LATER":
mmresponse.response = "NO"
if mmresponse.response == "YES":
await self.interface.bot.safe_api_call(client.send_message,
chat_id=mmresponse.royal.telegram[0].tg_id,
text=telegram_escape(started_string()),
parse_mode="HTML",
disable_webpage_preview=True)
else:
await self.interface.bot.safe_api_call(client.send_message,
chat_id=mmresponse.royal.telegram[0].tg_id,
text=telegram_escape(started_without_you_string),
parse_mode="HTML",
disable_webpage_preview=True)
await asyncify(session.commit)
await update_message()
async def start_key(data: CommandData):
royal = await data.get_author()
if royal == mmevent.creator:
await start_event()
if mmevent.state == "WAITING":
self.interface.register_keyboard_key(f"mm_{mmevent.mmid}_d_YES", decision_yes)
self.interface.register_keyboard_key(f"mm_{mmevent.mmid}_d_MAYBE", decision_maybe)
self.interface.register_keyboard_key(f"mm_{mmevent.mmid}_d_NO", decision_no)
await sleep_until(mmevent.datetime - datetime.timedelta(minutes=10))
self.interface.unregister_keyboard_key(f"mm_{mmevent.mmid}_d_YES")
self.interface.unregister_keyboard_key(f"mm_{mmevent.mmid}_d_MAYBE")
self.interface.unregister_keyboard_key(f"mm_{mmevent.mmid}_d_NO")
mmevent.state = "DECISION"
for mmdecision in mmevent.decisions:
mmdecision: MMDecision
if mmdecision.decision == "MAYBE":
await self.interface.bot.safe_api_call(client.send_message,
chat_id=mmdecision.royal.telegram[0].tg_id,
text=telegram_escape(decision_string),
parse_mode="HTML",
disable_webpage_preview=True,
reply_markup=decision_keyboard)
await asyncify(session.commit)
await update_message()
if mmevent.state == "DECISION":
self.interface.register_keyboard_key(f"mm_{mmevent.mmid}_d_YES", decision_yes)
self.interface.register_keyboard_key(f"mm_{mmevent.mmid}_d_NO", decision_no)
await sleep_until(mmevent.datetime)
self.interface.unregister_keyboard_key(f"mm_{mmevent.mmid}_d_YES")
self.interface.unregister_keyboard_key(f"mm_{mmevent.mmid}_d_NO")
mmevent.state = "READY_CHECK"
for mmdecision in mmevent.decisions:
if mmdecision.decision == "MAYBE":
mmdecision.decision = "NO"
elif mmdecision.decision == "YES":
mmresponse: MMResponse = self.interface.alchemy.MMResponse(royal=mmdecision.royal, mmevent=mmevent)
session.add(mmresponse)
await asyncify(session.commit)
await update_message()
if mmevent.state == "READY_CHECK":
self.interface.register_keyboard_key(f"mm_{mmevent.mmid}_r_YES", response_yes)
self.interface.register_keyboard_key(f"mm_{mmevent.mmid}_r_LATER", response_later)
self.interface.register_keyboard_key(f"mm_{mmevent.mmid}_r_NO", response_no)
self.interface.register_keyboard_key(f"mm_{mmevent.mmid}_forcestart", start_key)
cycle = 0
while True:
for mmresponse in mmevent.responses:
# Send messages
if mmresponse.response is None:
await self.interface.bot.safe_api_call(client.send_message,
chat_id=mmresponse.royal.telegram[0].tg_id,
text=telegram_escape(response_string()),
parse_mode="HTML",
disable_webpage_preview=True,
reply_markup=response_keyboard)
# Wait
await asyncio.sleep(60 * self._cycle_duration)
# Advance cycle
for mmresponse in mmevent.responses:
if mmresponse.response is None:
mmresponse.response = "NO"
if mmresponse.response == "LATER":
mmresponse.response = None
# Check if the event can start
for mmresponse in mmevent.responses:
if mmresponse.response is None:
break
else:
break
cycle += 1
await start_event()
self.interface.unregister_keyboard_key(f"mm_{mmevent.mmid}_r_YES")
self.interface.unregister_keyboard_key(f"mm_{mmevent.mmid}_r_LATER")
self.interface.unregister_keyboard_key(f"mm_{mmevent.mmid}_r_NO")
self.interface.unregister_keyboard_key(f"mm_{mmevent.mmid}_forcestart")
def __init__(self, interface):
super().__init__(interface)
# if self.interface.name != "telegram":
# return
# log.debug("Loading pending MMEvents from the database")
# 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:
# session = interface.alchemy.Session()
# new_mmevent = session.query(MMEvent).get(mmevent.mmid)
# interface.loop.create_task(self._run_mm(new_mmevent, session, close_at_end=True))
# session.close()
async def run(self, args: CommandArgs, data: CommandData) -> None:
raise UnsupportedError("MmCommand è attualmente disabilitato per via di bug introdotti da cambiamenti nella"
" gestione del database del bot.")
# if self.interface.name != "telegram":
# raise UnsupportedError("mm is supported only on Telegram")
# client: telegram.Bot = self.interface.bot.client
# creator = await data.get_author(error_if_none=True)
# try:
# timestring, title, description = args.match(r"\[\s*([^]]+)\s*]\s*([^\n]+)\s*\n?\s*(.+)?\s*", re.DOTALL)
# except InvalidInputError:
# timestring, title, description = args.match(r"\s*(.+?)\s*\n\s*([^\n]+)\s*\n?\s*(.+)?\s*", re.DOTALL)
# try:
# dt: typing.Optional[datetime.datetime] = dateparser.parse(timestring, settings={
# "PREFER_DATES_FROM": "future"
# })
# except OverflowError:
# dt = None
# if dt is None:
# await data.reply("⚠️ La data che hai specificato non è valida.")
# return
# if dt <= datetime.datetime.now():
# await data.reply("⚠️ La data che hai specificato è nel passato.")
# return
# mmevent: MMEvent = self.interface.alchemy.MMEvent(creator=creator,
# datetime=dt,
# title=title,
# description=description,
# state="WAITING")
# data.session.add(mmevent)
# await asyncify(data.session.commit)
#
# message: telegram.Message = await self.interface.bot.safe_api_call(client.send_message,
# chat_id=-1001287169422,
# 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(data.session.commit)
#
# await self._run_mm(mmevent, data.session)

View file

@ -13,7 +13,7 @@ class Mp3Command(Command):
description: str = "Scarica un video con youtube-dl e invialo in chat." description: str = "Scarica un video con youtube-dl e invialo in chat."
syntax = "(ytdlstring)" syntax = "{ytdlstring}"
ytdl_args = { ytdl_args = {
"format": "bestaudio", "format": "bestaudio",

View file

@ -15,7 +15,7 @@ class PlayCommand(Command):
description: str = "Aggiunge un url alla coda della chat vocale." description: str = "Aggiunge un url alla coda della chat vocale."
syntax = "[ [guild] ] (url)" syntax = "[ [guild] ] {url}"
@staticmethod @staticmethod
async def _legacy_play_handler(bot: "DiscordBot", guild_name: typing.Optional[str], url: str): async def _legacy_play_handler(bot: "DiscordBot", guild_name: typing.Optional[str], url: str):

View file

@ -12,7 +12,7 @@ class PlaymodeCommand(Command):
description: str = "Cambia modalità di riproduzione per la chat vocale." description: str = "Cambia modalità di riproduzione per la chat vocale."
syntax = "[ [guild] ] (mode)" syntax = "[ [guild] ] {mode}"
@staticmethod @staticmethod
async def _legacy_playmode_handler(bot: "DiscordBot", guild_name: typing.Optional[str], mode_name: str): async def _legacy_playmode_handler(bot: "DiscordBot", guild_name: typing.Optional[str], mode_name: str):

View file

@ -17,7 +17,7 @@ class ReminderCommand(Command):
description: str = "Ti ricorda di fare qualcosa dopo un po' di tempo." description: str = "Ti ricorda di fare qualcosa dopo un po' di tempo."
syntax: str = "[ (data) ] (messaggio)" syntax: str = "[ {data} ] {messaggio}"
tables = {Reminder} tables = {Reminder}
@ -37,7 +37,7 @@ class ReminderCommand(Command):
async def _remind(self, reminder): async def _remind(self, reminder):
await sleep_until(reminder.datetime) await sleep_until(reminder.datetime)
if self.interface.name == "telegram": if self.interface.name == "telegram":
chat_id: int = pickle.loads(reminder.interface_data) chat_id: int = pickle.loads(reminder.raw_interface_data)
bot: telegram.Bot = self.interface.bot.client bot: telegram.Bot = self.interface.bot.client
await asyncify(bot.send_message, await asyncify(bot.send_message,
chat_id=chat_id, chat_id=chat_id,
@ -45,7 +45,7 @@ class ReminderCommand(Command):
parse_mode="HTML", parse_mode="HTML",
disable_web_page_preview=True) disable_web_page_preview=True)
elif self.interface.name == "discord": elif self.interface.name == "discord":
channel_id: int = pickle.loads(reminder.interface_data) channel_id: int = pickle.loads(reminder.raw_interface_data)
bot: discord.Client = self.interface.bot.client bot: discord.Client = self.interface.bot.client
channel = bot.get_channel(channel_id) channel = bot.get_channel(channel_id)
await channel.send(discord_escape(f"❗️ {reminder.message}")) await channel.send(discord_escape(f"❗️ {reminder.message}"))

View file

@ -11,7 +11,7 @@ class ShipCommand(Command):
description: str = "Crea una ship tra due nomi." description: str = "Crea una ship tra due nomi."
syntax = "(nomeuno) (nomedue)" syntax = "{nomeuno} {nomedue}"
async def run(self, args: CommandArgs, data: CommandData) -> None: async def run(self, args: CommandArgs, data: CommandData) -> None:
name_one = args[0] name_one = args[0]

View file

@ -15,7 +15,7 @@ class SoundcloudCommand(Command):
description: str = "Cerca una canzone su Soundcloud e la aggiunge alla coda della chat vocale." description: str = "Cerca una canzone su Soundcloud e la aggiunge alla coda della chat vocale."
syntax = "[ [guild] ] (url)" syntax = "[ [guild] ] {url}"
@staticmethod @staticmethod
async def _legacy_soundcloud_handler(bot: "DiscordBot", guild_name: typing.Optional[str], search: str): async def _legacy_soundcloud_handler(bot: "DiscordBot", guild_name: typing.Optional[str], search: str):

View file

@ -15,7 +15,7 @@ class YoutubeCommand(Command):
description: str = "Cerca un video su YouTube e lo aggiunge alla coda della chat vocale." description: str = "Cerca un video su YouTube e lo aggiunge alla coda della chat vocale."
syntax = "[ [guild] ] (url)" syntax = "[ [guild] ] {url}"
@classmethod @classmethod
async def _legacy_youtube_handler(cls, bot: "DiscordBot", guild_name: typing.Optional[str], search: str): async def _legacy_youtube_handler(cls, bot: "DiscordBot", guild_name: typing.Optional[str], search: str):

View file

@ -10,7 +10,6 @@ from .wikirevisions import WikiRevision
from .bios import Bio from .bios import Bio
from .reminders import Reminder from .reminders import Reminder
from .triviascores import TriviaScore from .triviascores import TriviaScore
from .mmdecisions import MMDecision
from .mmevents import MMEvent from .mmevents import MMEvent
from .mmresponse import MMResponse from .mmresponse import MMResponse
@ -26,7 +25,6 @@ available_tables = [
Bio, Bio,
Reminder, Reminder,
TriviaScore, TriviaScore,
MMDecision,
MMEvent, MMEvent,
MMResponse, MMResponse,
] ]

View file

@ -1,34 +0,0 @@
from sqlalchemy import Column, \
Integer, \
String, \
ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declared_attr
class MMDecision:
__tablename__ = "mmdecisions"
@declared_attr
def royal_id(self):
return Column(Integer, ForeignKey("users.uid"), primary_key=True)
@declared_attr
def royal(self):
return relationship("User", backref="mmdecisions_taken")
@declared_attr
def mmevent_id(self):
return Column(Integer, ForeignKey("mmevents.mmid"), primary_key=True)
@declared_attr
def mmevent(self):
return relationship("MMEvent", backref="decisions")
@declared_attr
def decision(self):
# Valid decisions are YES, MAYBE or NO
return Column(String, nullable=False)
def __repr__(self):
return f"<MMDecision of {self.royal}: {self.decision}>"

View file

@ -1,10 +1,5 @@
from sqlalchemy import Column, \ import pickle
Integer, \ from sqlalchemy import *
DateTime, \
String, \
Text, \
ForeignKey, \
BigInteger
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.ext.declarative import declared_attr
@ -37,14 +32,21 @@ class MMEvent:
return Column(Text, nullable=False, default="") return Column(Text, nullable=False, default="")
@declared_attr @declared_attr
def state(self): def interface(self):
# Valid states are WAITING, DECISION, READY_CHECK, STARTED return Column(String, nullable=False)
return Column(String, nullable=False, default="WAITING")
@declared_attr @declared_attr
def message_id(self): def raw_interface_data(self):
return Column(BigInteger) # The default is a pickled None
return Column(Binary, nullable=False, default=b'\x80\x03N.')
@property
def interface_data(self):
return pickle.loads(self.raw_interface_data)
@interface_data.setter
def interface_data(self, value):
self.raw_interface_data = pickle.dumps(value)
def __repr__(self): def __repr__(self):
return f"<MMEvent {self.mmid}: {self.title}>" return f"<MMEvent {self.mmid}: {self.title}>"

View file

@ -1,9 +1,7 @@
from sqlalchemy import Column, \ from sqlalchemy import *
Integer, \
String, \
ForeignKey
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.ext.declarative import declared_attr
from ..utils import MMChoice
class MMResponse: class MMResponse:
@ -26,9 +24,8 @@ class MMResponse:
return relationship("MMEvent", backref="responses") return relationship("MMEvent", backref="responses")
@declared_attr @declared_attr
def response(self): def choice(self):
# Valid decisions are YES, LATER or NO return Column(Enum(MMChoice), nullable=False)
return Column(String)
def __repr__(self): def __repr__(self):
return f"<MMResponse of {self.royal}: {self.response}>" return f"<MMResponse of {self.royal}: {self.choice}>"

View file

@ -0,0 +1,4 @@
from .mmchoice import MMChoice
from .mminterfacedata import MMInterfaceData, MMInterfaceDataTelegram
__all__ = ["MMChoice", "MMInterfaceData", "MMInterfaceDataTelegram"]

View file

@ -0,0 +1,12 @@
import enum
class MMChoice(enum.Enum):
YES = "🔵"
MAYBE = ""
LATE_SHORT = "🕐"
LATE_MEDIUM = "🕒"
LATE_LONG = "🕗"
NO_TIME = "🔴"
NO_INTEREST = ""
NO_TECH = "❗️"

View file

@ -0,0 +1,10 @@
class MMInterfaceData:
def __init__(self):
pass
class MMInterfaceDataTelegram(MMInterfaceData):
def __init__(self, chat_id: int, message_id: int):
super().__init__()
self.chat_id = chat_id
self.message_id = message_id