2020-01-16 02:00:35 +00:00
|
|
|
|
from typing import *
|
|
|
|
|
import asyncio
|
|
|
|
|
import aiohttp
|
|
|
|
|
import random
|
|
|
|
|
import uuid
|
|
|
|
|
import html
|
|
|
|
|
import royalnet.commands as rc
|
|
|
|
|
import royalnet.utils as ru
|
2020-05-10 22:46:12 +00:00
|
|
|
|
import royalnet.backpack.tables as rbt
|
2020-01-16 02:00:35 +00:00
|
|
|
|
from ..tables import TriviaScore
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TriviaCommand(rc.Command):
|
|
|
|
|
name: str = "trivia"
|
|
|
|
|
|
|
|
|
|
aliases = ["t"]
|
|
|
|
|
|
|
|
|
|
description: str = "Manda una domanda dell'OpenTDB in chat."
|
|
|
|
|
|
|
|
|
|
syntax = "[credits|scores]"
|
|
|
|
|
|
|
|
|
|
_letter_emojis = ["🇦", "🇧", "🇨", "🇩"]
|
|
|
|
|
|
|
|
|
|
_medal_emojis = ["🥇", "🥈", "🥉", "🔹"]
|
|
|
|
|
|
|
|
|
|
_correct_emoji = "✅"
|
|
|
|
|
|
|
|
|
|
_wrong_emoji = "❌"
|
|
|
|
|
|
2020-01-17 16:59:30 +00:00
|
|
|
|
_answer_time = 20
|
2020-01-16 02:00:35 +00:00
|
|
|
|
|
2020-01-17 17:00:28 +00:00
|
|
|
|
# _question_lock: bool = False
|
2020-01-16 02:00:35 +00:00
|
|
|
|
|
2020-08-20 01:20:53 +00:00
|
|
|
|
def __init__(self, serf, config):
|
|
|
|
|
super().__init__(serf, config)
|
2020-01-16 02:00:35 +00:00
|
|
|
|
self._answerers: Dict[uuid.UUID, Dict[str, bool]] = {}
|
|
|
|
|
|
|
|
|
|
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
|
|
|
|
|
arg = args.optional(0)
|
2020-08-20 01:20:53 +00:00
|
|
|
|
async with data.session_acm() as session:
|
|
|
|
|
if arg == "credits":
|
|
|
|
|
await data.reply(f"ℹ️ [c]{self.serf.prefix}{self.name}[/c] di [i]Steffo[/i]\n"
|
|
|
|
|
f"\n"
|
|
|
|
|
f"Tutte le domande vengono dall'[b]Open Trivia Database[/b] di [i]Pixeltail Games[/i],"
|
|
|
|
|
f" creatori di Tower Unite, e sono rilasciate sotto la licenza [b]CC BY-SA 4.0[/b].")
|
|
|
|
|
return
|
|
|
|
|
elif arg == "scores":
|
|
|
|
|
trivia_scores = await ru.asyncify(session.query(self.alchemy.get(TriviaScore)).all)
|
|
|
|
|
strings = ["🏆 [b]Trivia Leaderboards[/b]\n"]
|
|
|
|
|
for index, ts in enumerate(sorted(trivia_scores, key=lambda ts: -ts.score)):
|
|
|
|
|
if index > 3:
|
|
|
|
|
index = 3
|
|
|
|
|
strings.append(f"{self._medal_emojis[index]} {ts.user.username}: [b]{ts.score:.0f}p[/b]"
|
|
|
|
|
f" ({ts.correct_answers}/{ts.total_answers})")
|
|
|
|
|
await data.reply("\n".join(strings))
|
|
|
|
|
return
|
|
|
|
|
# if self._question_lock:
|
|
|
|
|
# raise rc.CommandError("C'è già un'altra domanda attiva!")
|
|
|
|
|
# self._question_lock = True
|
|
|
|
|
# Fetch the question
|
|
|
|
|
async with aiohttp.ClientSession() as ws:
|
|
|
|
|
async with ws.get("https://opentdb.com/api.php?amount=1") as response:
|
|
|
|
|
j = await response.json()
|
|
|
|
|
# Parse the question
|
|
|
|
|
if j["response_code"] != 0:
|
|
|
|
|
raise rc.CommandError(f"OpenTDB returned an error response_code ({j['response_code']}).")
|
|
|
|
|
question = j["results"][0]
|
|
|
|
|
text = f'❓ [b]{question["category"]}[/b]\n' \
|
|
|
|
|
f'{html.unescape(question["question"])}'
|
|
|
|
|
# Prepare answers
|
|
|
|
|
correct_answer: str = question["correct_answer"]
|
|
|
|
|
wrong_answers: List[str] = question["incorrect_answers"]
|
|
|
|
|
answers: List[str] = [correct_answer, *wrong_answers]
|
|
|
|
|
if question["type"] == "multiple":
|
|
|
|
|
random.shuffle(answers)
|
|
|
|
|
elif question["type"] == "boolean":
|
|
|
|
|
answers.sort(key=lambda a: a)
|
|
|
|
|
answers.reverse()
|
2020-01-16 02:00:35 +00:00
|
|
|
|
else:
|
2020-08-20 01:20:53 +00:00
|
|
|
|
raise NotImplementedError("Unknown question type")
|
|
|
|
|
# Find the correct index
|
|
|
|
|
for index, answer in enumerate(answers):
|
|
|
|
|
if answer == correct_answer:
|
|
|
|
|
correct_index = index
|
|
|
|
|
break
|
2020-01-16 02:00:35 +00:00
|
|
|
|
else:
|
2020-08-20 01:20:53 +00:00
|
|
|
|
raise ValueError("correct_index not found")
|
|
|
|
|
# Add emojis
|
|
|
|
|
for index, answer in enumerate(answers):
|
|
|
|
|
answers[index] = f"{self._letter_emojis[index]} {html.unescape(answers[index])}"
|
|
|
|
|
# Create the question id
|
|
|
|
|
question_id = uuid.uuid4()
|
|
|
|
|
self._answerers[question_id] = {}
|
|
|
|
|
|
|
|
|
|
# Create the correct and wrong functions
|
|
|
|
|
async def correct(data: rc.CommandData):
|
2020-08-23 22:13:38 +00:00
|
|
|
|
answerer_ = await data.find_author(session=session, required=True)
|
2020-08-20 01:20:53 +00:00
|
|
|
|
try:
|
|
|
|
|
self._answerers[question_id][answerer_.uid] = True
|
|
|
|
|
except KeyError:
|
|
|
|
|
raise rc.UserError("Tempo scaduto!")
|
|
|
|
|
await data.reply("🆗 Hai risposto alla domanda. Ora aspetta un attimo per i risultati!")
|
|
|
|
|
|
|
|
|
|
async def wrong(data: rc.CommandData):
|
2020-08-23 22:13:38 +00:00
|
|
|
|
answerer_ = await data.find_author(session=session, required=True)
|
2020-08-20 01:20:53 +00:00
|
|
|
|
try:
|
|
|
|
|
self._answerers[question_id][answerer_.uid] = False
|
|
|
|
|
except KeyError:
|
|
|
|
|
raise rc.UserError("Tempo scaduto!")
|
|
|
|
|
await data.reply("🆗 Hai risposto alla domanda. Ora aspetta un attimo per i risultati!")
|
|
|
|
|
|
|
|
|
|
# Add question
|
|
|
|
|
keyboard: List[rc.KeyboardKey] = []
|
|
|
|
|
for index, answer in enumerate(answers):
|
|
|
|
|
if index == correct_index:
|
|
|
|
|
keyboard.append(rc.KeyboardKey(short=self._letter_emojis[index],
|
|
|
|
|
text=answers[index],
|
|
|
|
|
callback=correct))
|
|
|
|
|
else:
|
|
|
|
|
keyboard.append(rc.KeyboardKey(short=self._letter_emojis[index],
|
|
|
|
|
text=answers[index],
|
|
|
|
|
callback=wrong))
|
|
|
|
|
async with data.keyboard(text=text, keys=keyboard):
|
|
|
|
|
await asyncio.sleep(self._answer_time)
|
|
|
|
|
results = f"❗️ Tempo scaduto!\n" \
|
|
|
|
|
f"La risposta corretta era [b]{answers[correct_index]}[/b]!\n\n"
|
|
|
|
|
for answerer_id in self._answerers[question_id]:
|
|
|
|
|
answerer = session.query(self.alchemy.get(rbt.users.User)).get(answerer_id)
|
|
|
|
|
if answerer.trivia_score is None:
|
|
|
|
|
ts = self.alchemy.get(TriviaScore)(user=answerer)
|
|
|
|
|
session.add(ts)
|
|
|
|
|
await ru.asyncify(session.commit)
|
|
|
|
|
previous_score = answerer.trivia_score.score
|
|
|
|
|
if self._answerers[question_id][answerer_id]:
|
|
|
|
|
results += self._correct_emoji
|
|
|
|
|
answerer.trivia_score.correct_answers += 1
|
|
|
|
|
else:
|
|
|
|
|
results += self._wrong_emoji
|
|
|
|
|
answerer.trivia_score.wrong_answers += 1
|
|
|
|
|
current_score = answerer.trivia_score.score
|
|
|
|
|
score_difference = current_score - previous_score
|
|
|
|
|
results += f" {answerer}: [b]{current_score:.0f}p[/b] ({score_difference:+.0f}p)\n"
|
|
|
|
|
await data.reply(results)
|
|
|
|
|
del self._answerers[question_id]
|
|
|
|
|
await ru.asyncify(session.commit)
|
|
|
|
|
# self._question_lock = False
|