mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-12-08 10:22:31 -05:00
First commit
This commit is contained in:
214
cogs/trivia.py
Normal file
214
cogs/trivia.py
Normal file
@@ -0,0 +1,214 @@
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from random import randint
|
||||
from random import choice as randchoice
|
||||
import datetime
|
||||
import time
|
||||
import os
|
||||
import asyncio
|
||||
|
||||
settings = {"TRIVIA_MAX_SCORE" : 10, "TRIVIA_TIMEOUT" : 120, "TRIVIA_DELAY" : 15, "TRIVIA_BOT_PLAYS" : False}
|
||||
|
||||
class Trivia:
|
||||
"""General commands."""
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.trivia_sessions = []
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
async def trivia(self, ctx, list_name : str=None):
|
||||
"""Start a trivia session with the specified list
|
||||
|
||||
Stop parameter will end the current session
|
||||
"""
|
||||
message = ctx.message
|
||||
if list_name == None:
|
||||
await self.triviaList(ctx.message.author)
|
||||
elif list_name.lower() == "stop":
|
||||
if await getTriviabyChannel(message.channel):
|
||||
s = await getTriviabyChannel(message.channel)
|
||||
await s.endGame()
|
||||
await self.bot.say("`Trivia stopped.`")
|
||||
else:
|
||||
await self.bot.say("`There's no trivia session ongoing in this channel.`")
|
||||
elif not await getTriviabyChannel(message.channel):
|
||||
t = TriviaSession(message)
|
||||
self.trivia_sessions.append(t)
|
||||
await t.loadQuestions(message.content)
|
||||
else:
|
||||
await self.bot.say("`A trivia session is already ongoing in this channel.`")
|
||||
|
||||
async def triviaList(self, author):
|
||||
msg = "**Available trivia lists:** \n\n```"
|
||||
lists = os.listdir("data/trivia/")
|
||||
if lists:
|
||||
clean_list = []
|
||||
for txt in lists:
|
||||
if txt.endswith(".txt") and " " not in txt:
|
||||
txt = txt.replace(".txt", "")
|
||||
clean_list.append(txt)
|
||||
if clean_list:
|
||||
for i, d in enumerate(clean_list):
|
||||
if i % 4 == 0 and i != 0:
|
||||
msg = msg + d + "\n"
|
||||
else:
|
||||
msg = msg + d + "\t"
|
||||
msg += "```"
|
||||
await self.bot.send_message(author, msg)
|
||||
else:
|
||||
await self.bot.say("There are no trivia lists available.")
|
||||
else:
|
||||
await self.bot.say("There are no trivia lists available.")
|
||||
|
||||
class TriviaSession():
|
||||
def __init__(self, message):
|
||||
self.gaveAnswer = ["I know this one! {}!", "Easy: {}.", "Oh really? It's {} of course."]
|
||||
self.currentQ = None # {"QUESTION" : "String", "ANSWERS" : []}
|
||||
self.questionList = ""
|
||||
self.channel = message.channel
|
||||
self.scoreList = {}
|
||||
self.status = None
|
||||
self.timer = None
|
||||
self.count = 0
|
||||
|
||||
async def loadQuestions(self, msg):
|
||||
msg = msg.split(" ")
|
||||
if len(msg) == 2:
|
||||
_, qlist = msg
|
||||
if qlist == "random":
|
||||
chosenList = randchoice(glob.glob("data/trivia/*.txt"))
|
||||
self.questionList = self.loadList(chosenList)
|
||||
self.status = "new question"
|
||||
self.timeout = time.perf_counter()
|
||||
if self.questionList: await self.newQuestion()
|
||||
else:
|
||||
if os.path.isfile("data/trivia/" + qlist + ".txt"):
|
||||
self.questionList = self.loadList("trivia/" + qlist + ".txt")
|
||||
self.status = "new question"
|
||||
self.timeout = time.perf_counter()
|
||||
if self.questionList: await self.newQuestion()
|
||||
else:
|
||||
await triviaManager.bot.say("`There is no list with that name.`")
|
||||
await self.stopTrivia()
|
||||
else:
|
||||
await triviaManager.bot.say("`trivia [list name]`")
|
||||
|
||||
async def stopTrivia(self):
|
||||
self.status = "stop"
|
||||
triviaManager.trivia_sessions.remove(self)
|
||||
|
||||
async def endGame(self):
|
||||
self.status = "stop"
|
||||
if self.scoreList:
|
||||
await self.sendTable()
|
||||
triviaManager.trivia_sessions.remove(self)
|
||||
|
||||
def loadList(self, qlist):
|
||||
with open(qlist, "r", encoding="utf-8") as f:
|
||||
qlist = f.readlines()
|
||||
parsedList = []
|
||||
for line in qlist:
|
||||
if "`" in line and len(line) > 4:
|
||||
line = line.replace("\n", "")
|
||||
line = line.split("`")
|
||||
question = line[0]
|
||||
answers = []
|
||||
for l in line[1:]:
|
||||
answers.append(l.lower())
|
||||
if len(line) >= 2:
|
||||
line = {"QUESTION" : question, "ANSWERS": answers} #string, list
|
||||
parsedList.append(line)
|
||||
if parsedList != []:
|
||||
return parsedList
|
||||
else:
|
||||
self.stopTrivia()
|
||||
return None
|
||||
|
||||
async def newQuestion(self):
|
||||
for score in self.scoreList.values():
|
||||
if score == settings["TRIVIA_MAX_SCORE"]:
|
||||
await self.endGame()
|
||||
return True
|
||||
if self.questionList == []:
|
||||
await self.endGame()
|
||||
return True
|
||||
self.currentQ = randchoice(self.questionList)
|
||||
self.questionList.remove(self.currentQ)
|
||||
self.status = "waiting for answer"
|
||||
self.count += 1
|
||||
self.timer = int(time.perf_counter())
|
||||
await triviaManager.bot.say("**Question number {}!**\n\n{}".format(str(self.count), self.currentQ["QUESTION"]))
|
||||
while self.status != "correct answer" and abs(self.timer - int(time.perf_counter())) <= settings["TRIVIA_DELAY"]:
|
||||
if abs(self.timeout - int(time.perf_counter())) >= settings["TRIVIA_TIMEOUT"]:
|
||||
await triviaManager.bot.say("Guys...? Well, I guess I'll stop then.")
|
||||
await self.stopTrivia()
|
||||
return True
|
||||
await asyncio.sleep(1) #Waiting for an answer or for the time limit
|
||||
if self.status == "correct answer":
|
||||
self.status = "new question"
|
||||
await asyncio.sleep(3)
|
||||
if not self.status == "stop":
|
||||
await self.newQuestion()
|
||||
elif self.status == "stop":
|
||||
return True
|
||||
else:
|
||||
msg = randchoice(self.gaveAnswer).format(self.currentQ["ANSWERS"][0])
|
||||
if settings["TRIVIA_BOT_PLAYS"]:
|
||||
msg += " **+1** for me!"
|
||||
self.addPoint(self.bot.user.name)
|
||||
self.currentQ["ANSWERS"] = []
|
||||
await triviaManager.bot.say(msg)
|
||||
await triviaManager.bot.send_typing(self.channel)
|
||||
await asyncio.sleep(3)
|
||||
if not self.status == "stop":
|
||||
await self.newQuestion()
|
||||
|
||||
async def sendTable(self):
|
||||
self.scoreList = sorted(self.scoreList.items(), reverse=True, key=lambda x: x[1]) # orders score from lower to higher
|
||||
t = "```Scores: \n\n"
|
||||
for score in self.scoreList:
|
||||
t += score[0] # name
|
||||
t += "\t"
|
||||
t += str(score[1]) # score
|
||||
t += "\n"
|
||||
t += "```"
|
||||
await triviaManager.bot.say(t)
|
||||
|
||||
async def checkAnswer(self, message):
|
||||
self.timeout = time.perf_counter()
|
||||
for answer in self.currentQ["ANSWERS"]:
|
||||
if answer in message.content.lower():
|
||||
self.currentQ["ANSWERS"] = []
|
||||
self.status = "correct answer"
|
||||
self.addPoint(message.author.name)
|
||||
await triviaManager.bot.send_message(message.channel, "You got it {}! **+1** to you!".format(message.author.name))
|
||||
await triviaManager.bot.send_typing(self.channel)
|
||||
return True
|
||||
|
||||
def addPoint(self, user):
|
||||
if user in self.scoreList:
|
||||
self.scoreList[user] += 1
|
||||
else:
|
||||
self.scoreList[user] = 1
|
||||
|
||||
def getTriviaQuestion(self):
|
||||
q = randchoice(list(trivia_questions.keys()))
|
||||
return q, trivia_questions[q] # question, answer
|
||||
|
||||
async def getTriviabyChannel(channel):
|
||||
for t in triviaManager.trivia_sessions:
|
||||
if t.channel == channel:
|
||||
return t
|
||||
return False
|
||||
|
||||
async def checkMessages(message):
|
||||
if message.author.id != triviaManager.bot.user.id:
|
||||
if await getTriviabyChannel(message.channel):
|
||||
trvsession = await getTriviabyChannel(message.channel)
|
||||
await trvsession.checkAnswer(message)
|
||||
|
||||
def setup(bot):
|
||||
global triviaManager
|
||||
bot.add_listener(checkMessages, "on_message")
|
||||
triviaManager = Trivia(bot)
|
||||
bot.add_cog(triviaManager)
|
||||
Reference in New Issue
Block a user