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:
parent
c7ebfe3622
commit
add6170183
21 changed files with 189 additions and 475 deletions
|
@ -11,7 +11,7 @@ from .videochannel import VideochannelCommand
|
|||
from .dnditem import DnditemCommand
|
||||
from .dndspell import DndspellCommand
|
||||
from .trivia import TriviaCommand
|
||||
from .mm import MmCommand
|
||||
from .matchmaking import MmCommand
|
||||
from .pause import PauseCommand
|
||||
from .play import PlayCommand
|
||||
from .playmode import PlaymodeCommand
|
||||
|
|
|
@ -10,7 +10,7 @@ class CvCommand(Command):
|
|||
|
||||
description: str = "Elenca le persone attualmente connesse alla chat vocale."
|
||||
|
||||
syntax: str = "[guildname] ['all']"
|
||||
syntax: str = "[guildname] [all]"
|
||||
|
||||
@staticmethod
|
||||
async def _legacy_cv_handler(bot: DiscordBot, guild_name: typing.Optional[str], everyone: bool):
|
||||
|
|
|
@ -33,7 +33,7 @@ class DiarioCommand(Command):
|
|||
|
||||
description: str = "Aggiungi una citazione al Diario."
|
||||
|
||||
syntax = "[!] \"(testo)\" --[autore], [contesto]"
|
||||
syntax = "[!] \"{testo}\" --[autore], [contesto]"
|
||||
|
||||
tables = {User, Diario, Alias}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ class DnditemCommand(Command):
|
|||
|
||||
description: str = "Ottieni informazioni su un oggetto di D&D5e."
|
||||
|
||||
syntax = "(nomeoggetto)"
|
||||
syntax = "{nomeoggetto}"
|
||||
|
||||
_dnddata: sortedcontainers.SortedKeyList = None
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ class DndspellCommand(Command):
|
|||
|
||||
description: str = "Ottieni informazioni su una magia di D&D5e."
|
||||
|
||||
syntax = "(nomemagia)"
|
||||
syntax = "{nomemagia}"
|
||||
|
||||
_dnddata: sortedcontainers.SortedKeyList = None
|
||||
|
||||
|
|
129
royalnet/packs/royal/commands/matchmaking.py
Normal file
129
royalnet/packs/royal/commands/matchmaking.py
Normal 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
|
||||
...
|
|
@ -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)
|
|
@ -13,7 +13,7 @@ class Mp3Command(Command):
|
|||
|
||||
description: str = "Scarica un video con youtube-dl e invialo in chat."
|
||||
|
||||
syntax = "(ytdlstring)"
|
||||
syntax = "{ytdlstring}"
|
||||
|
||||
ytdl_args = {
|
||||
"format": "bestaudio",
|
||||
|
|
|
@ -15,7 +15,7 @@ class PlayCommand(Command):
|
|||
|
||||
description: str = "Aggiunge un url alla coda della chat vocale."
|
||||
|
||||
syntax = "[ [guild] ] (url)"
|
||||
syntax = "[ [guild] ] {url}"
|
||||
|
||||
@staticmethod
|
||||
async def _legacy_play_handler(bot: "DiscordBot", guild_name: typing.Optional[str], url: str):
|
||||
|
|
|
@ -12,7 +12,7 @@ class PlaymodeCommand(Command):
|
|||
|
||||
description: str = "Cambia modalità di riproduzione per la chat vocale."
|
||||
|
||||
syntax = "[ [guild] ] (mode)"
|
||||
syntax = "[ [guild] ] {mode}"
|
||||
|
||||
@staticmethod
|
||||
async def _legacy_playmode_handler(bot: "DiscordBot", guild_name: typing.Optional[str], mode_name: str):
|
||||
|
|
|
@ -17,7 +17,7 @@ class ReminderCommand(Command):
|
|||
|
||||
description: str = "Ti ricorda di fare qualcosa dopo un po' di tempo."
|
||||
|
||||
syntax: str = "[ (data) ] (messaggio)"
|
||||
syntax: str = "[ {data} ] {messaggio}"
|
||||
|
||||
tables = {Reminder}
|
||||
|
||||
|
@ -37,7 +37,7 @@ class ReminderCommand(Command):
|
|||
async def _remind(self, reminder):
|
||||
await sleep_until(reminder.datetime)
|
||||
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
|
||||
await asyncify(bot.send_message,
|
||||
chat_id=chat_id,
|
||||
|
@ -45,7 +45,7 @@ class ReminderCommand(Command):
|
|||
parse_mode="HTML",
|
||||
disable_web_page_preview=True)
|
||||
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
|
||||
channel = bot.get_channel(channel_id)
|
||||
await channel.send(discord_escape(f"❗️ {reminder.message}"))
|
||||
|
|
|
@ -11,7 +11,7 @@ class ShipCommand(Command):
|
|||
|
||||
description: str = "Crea una ship tra due nomi."
|
||||
|
||||
syntax = "(nomeuno) (nomedue)"
|
||||
syntax = "{nomeuno} {nomedue}"
|
||||
|
||||
async def run(self, args: CommandArgs, data: CommandData) -> None:
|
||||
name_one = args[0]
|
||||
|
|
|
@ -15,7 +15,7 @@ class SoundcloudCommand(Command):
|
|||
|
||||
description: str = "Cerca una canzone su Soundcloud e la aggiunge alla coda della chat vocale."
|
||||
|
||||
syntax = "[ [guild] ] (url)"
|
||||
syntax = "[ [guild] ] {url}"
|
||||
|
||||
@staticmethod
|
||||
async def _legacy_soundcloud_handler(bot: "DiscordBot", guild_name: typing.Optional[str], search: str):
|
||||
|
|
|
@ -15,7 +15,7 @@ class YoutubeCommand(Command):
|
|||
|
||||
description: str = "Cerca un video su YouTube e lo aggiunge alla coda della chat vocale."
|
||||
|
||||
syntax = "[ [guild] ] (url)"
|
||||
syntax = "[ [guild] ] {url}"
|
||||
|
||||
@classmethod
|
||||
async def _legacy_youtube_handler(cls, bot: "DiscordBot", guild_name: typing.Optional[str], search: str):
|
||||
|
|
|
@ -10,7 +10,6 @@ from .wikirevisions import WikiRevision
|
|||
from .bios import Bio
|
||||
from .reminders import Reminder
|
||||
from .triviascores import TriviaScore
|
||||
from .mmdecisions import MMDecision
|
||||
from .mmevents import MMEvent
|
||||
from .mmresponse import MMResponse
|
||||
|
||||
|
@ -26,7 +25,6 @@ available_tables = [
|
|||
Bio,
|
||||
Reminder,
|
||||
TriviaScore,
|
||||
MMDecision,
|
||||
MMEvent,
|
||||
MMResponse,
|
||||
]
|
||||
|
|
|
@ -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}>"
|
|
@ -1,10 +1,5 @@
|
|||
from sqlalchemy import Column, \
|
||||
Integer, \
|
||||
DateTime, \
|
||||
String, \
|
||||
Text, \
|
||||
ForeignKey, \
|
||||
BigInteger
|
||||
import pickle
|
||||
from sqlalchemy import *
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
|
||||
|
@ -37,14 +32,21 @@ class MMEvent:
|
|||
return Column(Text, nullable=False, default="")
|
||||
|
||||
@declared_attr
|
||||
def state(self):
|
||||
# Valid states are WAITING, DECISION, READY_CHECK, STARTED
|
||||
return Column(String, nullable=False, default="WAITING")
|
||||
def interface(self):
|
||||
return Column(String, nullable=False)
|
||||
|
||||
@declared_attr
|
||||
def message_id(self):
|
||||
return Column(BigInteger)
|
||||
def raw_interface_data(self):
|
||||
# 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):
|
||||
return f"<MMEvent {self.mmid}: {self.title}>"
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
from sqlalchemy import Column, \
|
||||
Integer, \
|
||||
String, \
|
||||
ForeignKey
|
||||
from sqlalchemy import *
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
from ..utils import MMChoice
|
||||
|
||||
|
||||
class MMResponse:
|
||||
|
@ -26,9 +24,8 @@ class MMResponse:
|
|||
return relationship("MMEvent", backref="responses")
|
||||
|
||||
@declared_attr
|
||||
def response(self):
|
||||
# Valid decisions are YES, LATER or NO
|
||||
return Column(String)
|
||||
def choice(self):
|
||||
return Column(Enum(MMChoice), nullable=False)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<MMResponse of {self.royal}: {self.response}>"
|
||||
return f"<MMResponse of {self.royal}: {self.choice}>"
|
||||
|
|
4
royalnet/packs/royal/utils/__init__.py
Normal file
4
royalnet/packs/royal/utils/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
|||
from .mmchoice import MMChoice
|
||||
from .mminterfacedata import MMInterfaceData, MMInterfaceDataTelegram
|
||||
|
||||
__all__ = ["MMChoice", "MMInterfaceData", "MMInterfaceDataTelegram"]
|
12
royalnet/packs/royal/utils/mmchoice.py
Normal file
12
royalnet/packs/royal/utils/mmchoice.py
Normal 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 = "❗️"
|
10
royalnet/packs/royal/utils/mminterfacedata.py
Normal file
10
royalnet/packs/royal/utils/mminterfacedata.py
Normal 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
|
Loading…
Reference in a new issue