Bot V1
This commit is contained in:
211
bot.py
211
bot.py
@ -1,7 +1,9 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from asyncio.tasks import wait_for
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
from discord.message import Message
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
@ -24,13 +26,20 @@ class QuizClient(discord.Client):
|
|||||||
|
|
||||||
self.channel = None
|
self.channel = None
|
||||||
self.quiz = None
|
self.quiz = None
|
||||||
|
self.quizmaster = None
|
||||||
|
self.players = dict()
|
||||||
|
self.scores = list()
|
||||||
|
|
||||||
self.triggers = {} # automatic actions
|
self.triggers = {} # automatic actions
|
||||||
# Example: self.triggers[lambda m: "jeremy" in m.author.nick.lower()] = self.autoreact_to_jeremy
|
# Example: self.triggers[lambda m: "jeremy" in m.author.nick.lower()] = self.autoreact_to_jeremy
|
||||||
|
|
||||||
self.matchers = {} # react to messages
|
self.matchers = {} # react to messages
|
||||||
|
self.matchers["hilfe$"] = self.help
|
||||||
self.matchers["init: .*"] = self.init_quiz
|
self.matchers["init: .*"] = self.init_quiz
|
||||||
self.matchers["start"] = self.start_quiz
|
self.matchers["start$"] = self.run_quiz
|
||||||
|
self.matchers["reset$"] = self.reset_quiz
|
||||||
|
self.matchers["scores$"] = self.show_scores
|
||||||
|
self.matchers["players$"] = self.show_players
|
||||||
|
|
||||||
### Voicelines
|
### Voicelines
|
||||||
|
|
||||||
@ -86,58 +95,218 @@ class QuizClient(discord.Client):
|
|||||||
|
|
||||||
### Commands -----------------------------------------------------------------------------------
|
### Commands -----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
async def help(self, message):
|
||||||
|
"""
|
||||||
|
Quiz, hilfe - Hilfetext anzeigen
|
||||||
|
"""
|
||||||
|
await message.channel.send(self._help_text())
|
||||||
|
|
||||||
|
|
||||||
|
async def reset_quiz(self, message):
|
||||||
|
"""
|
||||||
|
Quiz, reset - Gesetzte Werte zurücksetzen (zum neu Initialisieren)
|
||||||
|
"""
|
||||||
|
await message.channel.send("Resetting...")
|
||||||
|
|
||||||
|
self.quiz = None
|
||||||
|
self.channel = None
|
||||||
|
self.quizmaster = None
|
||||||
|
self.players = dict()
|
||||||
|
self.scores = list()
|
||||||
|
|
||||||
|
await message.channel.send("Finished.")
|
||||||
|
|
||||||
|
|
||||||
|
def is_init(self):
|
||||||
|
return not (self.quiz == None or
|
||||||
|
self.channel == None or
|
||||||
|
self.quizmaster == None or
|
||||||
|
self.players == dict())
|
||||||
|
|
||||||
|
|
||||||
async def init_quiz(self, message):
|
async def init_quiz(self, message):
|
||||||
"""
|
"""
|
||||||
Quiz, init: [NAME] - Initialisiere ein neues Quiz.
|
Quiz, init: [NAME] - Initialisiere ein neues Quiz.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Set self.channel
|
# Reset to enable multiple inits
|
||||||
if "quiz" not in message.channel.name:
|
await self.reset_quiz(message)
|
||||||
await message.channel.send("Kein Quizchannel!")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
# Set self.channel
|
||||||
|
if "quiz" not in message.channel.name.lower():
|
||||||
|
await message.channel.send("Kein Quizchannel mann!")
|
||||||
|
return
|
||||||
self.channel = message.channel
|
self.channel = message.channel
|
||||||
await self.channel.send("Quiz starting in channel " + self.channel.name)
|
|
||||||
await self.channel.send("-" * 50)
|
# Set self.quizmaster
|
||||||
|
if message.author.top_role.name != "QuizMaster":
|
||||||
|
await self.channel.send("Nur für QuizMaster ey!")
|
||||||
|
return
|
||||||
|
self.quizmaster = message.author
|
||||||
|
|
||||||
# Set self.quiz
|
# Set self.quiz
|
||||||
self.quiz = Quiz((message.content.split(": "))[1])
|
try:
|
||||||
|
self.quiz = Quiz((message.content.split(": "))[1])
|
||||||
|
except:
|
||||||
|
await self.channel.send("Hab das Quiz nicht gefunden")
|
||||||
|
return
|
||||||
|
|
||||||
# Set self.players
|
# Set self.players
|
||||||
await self.channel.send("Determining players:")
|
await self.channel.send("Determining players:")
|
||||||
react_message = await self.channel.send("Hier mit individuellem Emoji reagieren, am Ende mit dem Haken bestätigen!")
|
react_message = await self.channel.send("Hier mit individuellem Emoji reagieren, am Ende mit dem Haken bestätigen!")
|
||||||
await react_message.add_reaction("✅")
|
await react_message.add_reaction("✅")
|
||||||
|
|
||||||
def check(reaction, user):
|
def check_confirm_players(reaction, user):
|
||||||
return reaction.message == react_message and str(reaction.emoji) == "✅" and user != client.user
|
return reaction.message == react_message and str(reaction.emoji) == "✅" and user == self.quizmaster
|
||||||
|
|
||||||
await self.wait_for('reaction_add', check=check)
|
await self.wait_for("reaction_add", check=check_confirm_players)
|
||||||
|
react_message = discord.utils.get(client.cached_messages, id=react_message.id)
|
||||||
|
assert isinstance(react_message, Message), "This should be a Message!" # silence pyright
|
||||||
|
|
||||||
# TODO: get players from emojis
|
# Get players from emojis
|
||||||
await self.channel.send("yay")
|
for reaction in react_message.reactions:
|
||||||
|
if reaction.emoji == "✅":
|
||||||
|
continue
|
||||||
|
|
||||||
|
async for user in reaction.users():
|
||||||
|
if user == self.quizmaster:
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.players[reaction.emoji] = user # TODO: key value which order?
|
||||||
|
|
||||||
|
# Send starting message
|
||||||
|
await self.channel.send("Quiz will start in channel \"" + self.channel.name + "\"")
|
||||||
|
await self.channel.send("Players:")
|
||||||
|
for emoji, player in self.players.items():
|
||||||
|
await self.channel.send(str(emoji) + ": " + str(player.display_name))
|
||||||
|
await self.channel.send("-" * 80)
|
||||||
|
|
||||||
|
|
||||||
async def start_quiz(self, message):
|
async def run_quiz(self, message):
|
||||||
"""
|
"""
|
||||||
Quiz, start - Starte das Quiz
|
Quiz, run - Starte das Quiz
|
||||||
"""
|
"""
|
||||||
if self.quiz == None or self.channel == None:
|
if not self.is_init():
|
||||||
await message.channel.send("Vorher init du kek")
|
await message.channel.send("Vorher init du kek")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if not message.author == self.quizmaster:
|
||||||
|
await self.channel.send("Kein QuizMaster kein Quiz!")
|
||||||
|
return
|
||||||
|
|
||||||
|
for question, answer in self.quiz:
|
||||||
|
|
||||||
|
# post question to players
|
||||||
|
for player in self.players.values():
|
||||||
|
await player.send("Frage: **" + question + "**")
|
||||||
|
|
||||||
|
# post question to channel for confirmation
|
||||||
|
await self.channel.send("Frage: **" + question + "**")
|
||||||
|
|
||||||
|
# wait for answers from all players
|
||||||
|
for player in self.players.values():
|
||||||
|
def check_answers_given(message):
|
||||||
|
return message.author == player
|
||||||
|
|
||||||
|
await self.wait_for("message", check=check_answers_given)
|
||||||
|
|
||||||
|
# wait for confirmation
|
||||||
|
cmsg = await self.channel.send("Alle Spieler haben geantwortet, fortfahren?")
|
||||||
|
await cmsg.add_reaction("✅")
|
||||||
|
|
||||||
|
def check_question_finished(reaction, user):
|
||||||
|
return reaction.message == cmsg and str(reaction.emoji) == "✅" and user == self.quizmaster
|
||||||
|
|
||||||
|
await self.wait_for("reaction_add", check=check_question_finished)
|
||||||
|
await self.channel.send("- " * 40)
|
||||||
|
|
||||||
|
# Antworten
|
||||||
|
await self.channel.send("**Antworten:**")
|
||||||
|
for emoji, player in self.players.items():
|
||||||
|
await self.channel.send(str(emoji) + ": " + str((await player.dm_channel.history(limit=1).flatten())[0].content))
|
||||||
|
|
||||||
|
amsg = await self.channel.send("Korrekte Antwort: " + answer)
|
||||||
|
await amsg.add_reaction("✅")
|
||||||
|
for emoji, player in self.players.items():
|
||||||
|
await amsg.add_reaction(emoji)
|
||||||
|
|
||||||
|
# Set Points
|
||||||
|
def check_confirm_points(reaction, user):
|
||||||
|
return reaction.message == amsg and str(reaction.emoji) == "✅" and user == self.quizmaster
|
||||||
|
|
||||||
|
await self.wait_for("reaction_add", check=check_confirm_points)
|
||||||
|
amsg = discord.utils.get(client.cached_messages, id=amsg.id)
|
||||||
|
assert isinstance(amsg, Message), "This should be a Message!" # silence pyright
|
||||||
|
|
||||||
|
turn_scores = list()
|
||||||
|
for reaction in amsg.reactions:
|
||||||
|
if reaction.emoji == "✅":
|
||||||
|
continue
|
||||||
|
|
||||||
|
async for user in reaction.users():
|
||||||
|
if user != self.quizmaster:
|
||||||
|
continue
|
||||||
|
|
||||||
|
turn_scores.append(reaction.emoji)
|
||||||
|
|
||||||
|
self.scores.append(turn_scores)
|
||||||
|
|
||||||
|
# Separators at the end
|
||||||
|
await self.channel.send("-" * 80)
|
||||||
|
for player in self.players.values():
|
||||||
|
await player.send("-" * 80)
|
||||||
|
|
||||||
|
await self.channel.send("Quiz vorbei!")
|
||||||
|
|
||||||
# Ablauf:
|
# Ablauf:
|
||||||
# - post question with green checkmark reaction
|
# - post question to quiz-channel and all private player channels
|
||||||
# - players post answers
|
# - players post answers in private bot-channel
|
||||||
# - answer multiple choice with a, b, c, d emojis
|
# - answer multiple choice with a, b, c, d emojis
|
||||||
# - close question with checkmark
|
# - bot reacts with green checkmark after everyone answered, then quizmaster can close with checkmark
|
||||||
# - print answer with player emojis
|
# - print answer with player emojis
|
||||||
# - automatic winner for number questions? robust? maybe only print but set manually.
|
|
||||||
# - set winners by choosing the right emoji
|
# - set winners by choosing the right emoji
|
||||||
#
|
#
|
||||||
#
|
|
||||||
# - track the points and make graphs
|
# - track the points and make graphs
|
||||||
|
|
||||||
|
|
||||||
|
async def show_scores(self, message):
|
||||||
|
"""
|
||||||
|
Quiz, scores - Zeigt den aktuellen Punktestand
|
||||||
|
"""
|
||||||
|
if not self.is_init():
|
||||||
|
await message.channel.send("Vorher init du kek")
|
||||||
|
return
|
||||||
|
|
||||||
|
if not message.author == self.quizmaster:
|
||||||
|
await self.channel.send("Kein QuizMaster keine Punkte!")
|
||||||
|
return
|
||||||
|
|
||||||
|
# scores = [[A, B], [A], [B, C], ...]
|
||||||
|
flat_scores = [player for round in self.scores for player in round]
|
||||||
|
score_dict = dict()
|
||||||
|
for emoji, _ in self.players.items():
|
||||||
|
score_dict[emoji] = len(list(filter(lambda x: x == emoji, flat_scores)))
|
||||||
|
|
||||||
|
await self.channel.send("Punktestand:")
|
||||||
|
for emoji, score in sorted(score_dict.items(), key=lambda item: item[1]):
|
||||||
|
await self.channel.send(str(emoji) + ": " + str(score) + " Punkte")
|
||||||
|
|
||||||
|
|
||||||
|
async def show_players(self, message):
|
||||||
|
"""
|
||||||
|
Quiz, players - Zeigt die Spielerliste
|
||||||
|
"""
|
||||||
|
if not self.is_init():
|
||||||
|
await message.channel.send("Vorher init du kek")
|
||||||
|
return
|
||||||
|
|
||||||
|
if not message.author == self.quizmaster:
|
||||||
|
await self.channel.send("Kein QuizMaster keine Punkte!")
|
||||||
|
return
|
||||||
|
|
||||||
|
await self.channel.send("Players:")
|
||||||
|
for emoji, player in self.players.items():
|
||||||
|
await self.channel.send(str(emoji) + ": " + str(player.display_name))
|
||||||
|
|
||||||
client = QuizClient()
|
client = QuizClient()
|
||||||
client.run(TOKEN)
|
client.run(TOKEN)
|
||||||
|
11
quiz.py
11
quiz.py
@ -9,3 +9,14 @@ class Quiz(object):
|
|||||||
for line in file:
|
for line in file:
|
||||||
question = tuple(string.strip() for string in tuple(line.split(" ")))
|
question = tuple(string.strip() for string in tuple(line.split(" ")))
|
||||||
self.questions.append(question)
|
self.questions.append(question)
|
||||||
|
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
def questions_gen(questions):
|
||||||
|
current = 0
|
||||||
|
|
||||||
|
while current < len(questions):
|
||||||
|
yield questions[current]
|
||||||
|
current += 1
|
||||||
|
|
||||||
|
return questions_gen(self.questions)
|
||||||
|
Reference in New Issue
Block a user