1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
import asyncio
import logging
import random
from json import loads
from pathlib import Path
from typing import Union
import discord
from discord.ext import commands
from bot.bot import Bot
from bot.constants import Colours
log = logging.getLogger(__name__)
EGGHEAD_QUESTIONS = loads(Path("bot/resources/holidays/easter/egghead_questions.json").read_text("utf8"))
EMOJIS = [
"\U0001f1e6", "\U0001f1e7", "\U0001f1e8", "\U0001f1e9", "\U0001f1ea",
"\U0001f1eb", "\U0001f1ec", "\U0001f1ed", "\U0001f1ee", "\U0001f1ef",
"\U0001f1f0", "\U0001f1f1", "\U0001f1f2", "\U0001f1f3", "\U0001f1f4",
"\U0001f1f5", "\U0001f1f6", "\U0001f1f7", "\U0001f1f8", "\U0001f1f9",
"\U0001f1fa", "\U0001f1fb", "\U0001f1fc", "\U0001f1fd", "\U0001f1fe",
"\U0001f1ff"
] # Regional Indicators A-Z (used for voting)
TIMELIMIT = 30
class EggheadQuiz(commands.Cog):
"""This cog contains the command for the Easter quiz!"""
def __init__(self):
self.quiz_messages = {}
@commands.command(aliases=("eggheadquiz", "easterquiz"))
async def eggquiz(self, ctx: commands.Context) -> None:
"""
Gives a random quiz question, waits 30 seconds and then outputs the answer.
Also informs of the percentages and votes of each option
"""
random_question = random.choice(EGGHEAD_QUESTIONS)
question, answers = random_question["question"], random_question["answers"]
answers = [(EMOJIS[i], a) for i, a in enumerate(answers)]
correct = EMOJIS[random_question["correct_answer"]]
valid_emojis = [emoji for emoji, _ in answers]
description = f"You have {TIMELIMIT} seconds to vote.\n\n"
description += "\n".join([f"{emoji} -> **{answer}**" for emoji, answer in answers])
q_embed = discord.Embed(title=question, description=description, colour=Colours.pink)
msg = await ctx.send(embed=q_embed)
for emoji in valid_emojis:
await msg.add_reaction(emoji)
self.quiz_messages[msg.id] = valid_emojis
await asyncio.sleep(TIMELIMIT)
del self.quiz_messages[msg.id]
msg = await ctx.fetch_message(msg.id) # Refreshes message
total_no = sum([len(await r.users().flatten()) for r in msg.reactions]) - len(valid_emojis) # - bot's reactions
if total_no == 0:
return await msg.delete() # To avoid ZeroDivisionError if nobody reacts
results = ["**VOTES:**"]
for emoji, _ in answers:
num = [len(await r.users().flatten()) for r in msg.reactions if str(r.emoji) == emoji][0] - 1
percent = round(100 * num / total_no)
s = "" if num == 1 else "s"
string = f"{emoji} - {num} vote{s} ({percent}%)"
results.append(string)
mentions = " ".join([
u.mention for u in [
await r.users().flatten() for r in msg.reactions if str(r.emoji) == correct
][0] if not u.bot
])
content = f"Well done {mentions} for getting it correct!" if mentions else "Nobody got it right..."
a_embed = discord.Embed(
title=f"The correct answer was {correct}!",
description="\n".join(results),
colour=Colours.pink
)
await ctx.send(content, embed=a_embed)
@staticmethod
async def already_reacted(message: discord.Message, user: Union[discord.Member, discord.User]) -> bool:
"""Returns whether a given user has reacted more than once to a given message."""
users = [u.id for reaction in [await r.users().flatten() for r in message.reactions] for u in reaction]
return users.count(user.id) > 1 # Old reaction plus new reaction
@commands.Cog.listener()
async def on_reaction_add(self, reaction: discord.Reaction, user: Union[discord.Member, discord.User]) -> None:
"""Listener to listen specifically for reactions of quiz messages."""
if user.bot:
return
if reaction.message.id not in self.quiz_messages:
return
if str(reaction.emoji) not in self.quiz_messages[reaction.message.id]:
return await reaction.message.remove_reaction(reaction, user)
if await self.already_reacted(reaction.message, user):
return await reaction.message.remove_reaction(reaction, user)
async def setup(bot: Bot) -> None:
"""Load the Egghead Quiz Cog."""
await bot.add_cog(EggheadQuiz())
|