Trivia

This commit is contained in:
NikolajDanger
2021-04-18 14:42:21 +02:00
committed by Nikolaj
parent 883f84f569
commit fd9bde73c6
2 changed files with 150 additions and 61 deletions

View File

@ -1,94 +1,175 @@
import json
import urllib
import random
import asyncio
"""
Contains code for trivia games.
*Classes*
---------
Trivia
Contains all the code for the trivia commands.
"""
import urllib # Used to get data from api
import json # Used to read data from api
import random # Used to shuffle answers
import asyncio # Used to sleep
from discord_slash.context import SlashContext # Used for type hints
class Trivia():
"""
Contains the code for trivia games.
*Methods*
---------
triviaStart(channel: str) -> str, str, str
triviaAnswer(user: str, channel: str, command: str) -> str
triviaCountPoints(channel: str)
triviaParse(ctx: SlashContext, answer: str)
"""
def __init__(self, bot):
"""Initialize the class."""
self.bot = bot
# Starts a game of trivia. Downloads a question with answers, shuffles the wrong answers with the
# correct answer and returns the questions and answers. Also saves the question in the games.json file.
def triviaStart(self, channel : str):
question = self.bot.database["trivia questions"].find_one({"_id":channel})
def triviaStart(self, channel: str):
"""
Start a game of trivia.
self.bot.log("Trying to find a trivia question for "+channel)
Downloads a question with answers, shuffles the wrong answers
with the correct answer and returns the questions and answers.
Also saves the question in the database.
if question == None:
with urllib.request.urlopen("https://opentdb.com/api.php?amount=10&type=multiple") as response:
*Parameters*
------------
channel: str
The id of the channel to start the game in
*Returns*
---------
sendMessage: str
The message to return to the user.
"""
triviaQuestions = self.bot.database["trivia questions"]
question = triviaQuestions.find_one({"_id": channel})
self.bot.log(f"Trying to find a trivia question for {channel}")
if question is None:
apiUrl = "https://opentdb.com/api.php?amount=10&type=multiple"
with urllib.request.urlopen(apiUrl) as response:
data = json.loads(response.read())
self.bot.log("Found the question \""+data["results"][0]["question"]+"\"")
question = data["results"][0]["question"]
self.bot.log(f"Found the question \"{question}\"")
answers = data["results"][0]["incorrect_answers"]
answers.append(data["results"][0]["correct_answer"])
random.shuffle(answers)
correctAnswer = answers.index(data["results"][0]["correct_answer"]) + 97
correctAnswer = data["results"][0]["correct_answer"]
correctAnswer = answers.index(correctAnswer) + 97
self.bot.database["trivia questions"].insert_one({"_id":channel,"answer" : str(chr(correctAnswer)),"players" : {}})
newQuestion = {
"_id": channel,
"answer": str(chr(correctAnswer)),
"players": {}
}
triviaQuestions.insert_one(newQuestion)
replacements = {"'": "\'",
replacements = {
"'": "\'",
""": "\"",
"“": "\"",
"”": "\"",
"é": "é"}
"é": "é"
}
question = data["results"][0]["question"]
for key, value in replacements.items():
question = question.replace(key,value)
question = question.replace(key, value)
for answer in answers:
for key, value in replacements.items():
answer = answer.replace(key,value)
answer = answer.replace(key, value)
return question, answers, correctAnswer
else:
self.bot.log("There was already a trivia question for that channel (error code 1106)")
return "There's already a trivia question going on. Try again in like, a minute (error code 1106)", "", ""
logMessage = "There was already a trivia question for that channel"
self.bot.log(logMessage)
return self.bot.longStrings["Trivia going on"], "", ""
# Lets players answer a trivia question
def triviaAnswer(self, user : str, channel : str, command : str):
question = self.bot.database["trivia questions"].find_one({"_id":channel})
def triviaAnswer(self, user: str, channel: str, command: str):
"""
Answer the current trivia question.
if command in ["a","b","c","d"]:
if question != None:
if user not in question["players"]:
self.bot.log(user+" answered the question in "+channel)
*Parameters*
------------
user: str
The id of the user who answered.
channel: str
The id of the channel the game is in.
command: str
The user's answer.
self.bot.database["trivia questions"].update_one({"_id":channel},{"$set":{"players."+user : command}})
*Returns*
---------
sendMessage: str
The message to send if the function failed.
"""
triviaQuestions = self.bot.database["trivia questions"]
question = triviaQuestions.find_one({"_id": channel})
return "Locked in "+user+"'s answer"
if command not in ["a", "b", "c", "d"]:
self.bot.log("I didn't quite understand that")
return "I didn't quite understand that"
elif question is None:
self.bot.log("There's no question right now")
return "There's no question right now"
elif user in question["players"]:
self.bot.log(f"{user} has already answered this question")
return f"{user} has already answered this question"
else:
self.bot.log(user+" has already answered this question (error code 1105)")
return user+" has already answered this question (error code 1105)"
else:
self.bot.log("There's no question right now (error code 1104)")
return "There's no question right now (error code 1104)"
else:
self.bot.log("I didn't quite understand that (error code 1103)")
return "I didn't quite understand that (error code 1103)"
self.bot.log(f"{user} answered the question in {channel}")
updater = {"$set": {f"players.{user}": command}}
triviaQuestions.update_one({"_id": channel}, updater)
return None
# Adds 1 GwendoBuck to each player that got the question right and deletes question from games.json.
def triviaCountPoints(self, channel : str):
question = self.bot.database["trivia questions"].find_one({"_id":channel})
def triviaCountPoints(self, channel: str):
"""
Add money to every winner's account.
*Parameters*
------------
channel: str
The id of the channel the game is in.
"""
triviaQuestions = self.bot.database["trivia questions"]
question = triviaQuestions.find_one({"_id": channel})
self.bot.log("Counting points for question in "+channel)
if question != None:
if question is not None:
for player, answer in question["players"].items():
if answer == question["answer"]:
self.bot.money.addMoney(player,1)
self.bot.money.addMoney(player, 1)
else:
self.bot.log("Couldn't find the question (error code 1102)")
self.bot.log("Couldn't find the questio")
return None
async def triviaParse(self, ctx, answer):
async def triviaParse(self, ctx: SlashContext, answer: str):
"""
Parse a trivia command.
*Parameters*
------------
ctx: SlashContext
The context of the command.
answer: str
The answer, if any.
"""
await self.bot.defer(ctx)
channelId = str(ctx.channel_id)
if answer == "":
question, options, correctAnswer = self.triviaStart(str(ctx.channel_id))
question, options, correctAnswer = self.triviaStart(channelId)
if options != "":
results = "**"+question+"**\n"
for x, option in enumerate(options):
@ -98,21 +179,27 @@ class Trivia():
await asyncio.sleep(60)
self.triviaCountPoints(str(ctx.channel_id))
self.triviaCountPoints(channelId)
self.bot.databaseFuncs.deleteGame("trivia questions",str(ctx.channel_id))
deleteGameParams = ["trivia questions", channelId]
self.bot.databaseFuncs.deleteGame(*deleteGameParams)
self.bot.log("Time's up for the trivia question",str(ctx.channel_id))
await ctx.send("Time's up The answer was \"*"+chr(correctAnswer)+") "+options[correctAnswer-97]+"*\". Anyone who answered that has gotten 1 GwendoBuck")
self.bot.log("Time's up for the trivia question", channelId)
sendMessage = self.bot.longStrings["Trivia time up"]
formatParams = [chr(correctAnswer), options[correctAnswer-97]]
sendMessage = sendMessage.format(*formatParams)
await ctx.send(sendMessage)
else:
await ctx.send(question, hidden=True)
elif answer in ["a","b","c","d"]:
response = self.triviaAnswer("#"+str(ctx.author.id), str(ctx.channel_id), answer)
if response.startswith("Locked in "):
await ctx.send(f"{ctx.author.display_name} answered **{answer}**")
elif answer in ["a", "b", "c", "d"]:
userId = f"#{ctx.author.id}"
response = self.triviaAnswer(userId, channelId, answer)
if response is None:
userName = ctx.author.display_name
await ctx.send(f"{userName} answered **{answer}**")
else:
await ctx.send(response)
else:
self.bot.log("I didn't understand that (error code 1101)",str(ctx.channel_id))
await ctx.send("I didn't understand that (error code 1101)")
self.bot.log("I didn't understand that", channelId)
await ctx.send("I didn't understand that")

View File

@ -10,5 +10,7 @@
"Blackjack started": "Blackjack game started. Use \"/blackjack bet [amount]\" to enter the game within the next 30 seconds.",
"Blackjack going on": "There's already a blackjack game going on. Try again in a few minutes.",
"Stock value": "The current {} stock is valued at **{}** GwendoBucks",
"Stock parameters": "You must give both a stock name and an amount of GwendoBucks you wish to spend."
"Stock parameters": "You must give both a stock name and an amount of GwendoBucks you wish to spend.",
"Trivia going on": "There's already a trivia question going on. Try again in like, a minute",
"Trivia time up": "Time's up! The answer was \"*{}) {}*\". Anyone who answered that has gotten 1 GwendoBuck"
}