[Trivia] Initial clean up, made proper commands

Fixes #681
This commit is contained in:
Twentysix 2017-03-31 07:25:13 +02:00
parent 5d5db20dcc
commit d757361d6e

View File

@ -1,15 +1,14 @@
import discord
from discord.ext import commands from discord.ext import commands
from random import randint from random import choice
from random import choice as randchoice
from .utils.dataIO import dataIO from .utils.dataIO import dataIO
from .utils import checks from .utils import checks
import datetime from .utils.chat_formatting import box
import time import time
import os import os
import asyncio import asyncio
import chardet import chardet
class Trivia: class Trivia:
"""General commands.""" """General commands."""
def __init__(self, bot): def __init__(self, bot):
@ -60,98 +59,96 @@ class Trivia:
await self.bot.say("I'll gain a point everytime you don't answer in time.") await self.bot.say("I'll gain a point everytime you don't answer in time.")
dataIO.save_json(self.file_path, self.settings) dataIO.save_json(self.file_path, self.settings)
@commands.command(pass_context=True) @commands.group(pass_context=True, invoke_without_command=True)
async def trivia(self, ctx, list_name : str=None): async def trivia(self, ctx, list_name: str):
"""Start a trivia session with the specified list """Start a trivia session with the specified list"""
trivia stop - Ends the current session
trivia - Shows trivia lists
"""
message = ctx.message message = ctx.message
if list_name == None: session = self.get_trivia_by_channel(message.channel)
await self.trivia_list(ctx.message.author) if not session:
elif list_name.lower() == "stop": t = TriviaSession(self.bot, message.channel, self.settings)
if await get_trivia_by_channel(message.channel):
s = await get_trivia_by_channel(message.channel)
await s.end_game()
await self.bot.say("Trivia stopped.")
else:
await self.bot.say("There's no trivia session ongoing in this channel.")
elif not await get_trivia_by_channel(message.channel):
t = TriviaSession(message, self.settings)
self.trivia_sessions.append(t) self.trivia_sessions.append(t)
await t.load_questions(message.content) await t.load_questions(list_name)
else: else:
await self.bot.say("A trivia session is already ongoing in this channel.") await self.bot.say("A trivia session is already ongoing in this channel.")
async def trivia_list(self, author): @trivia.group(name="stop", pass_context=True)
msg = "**Available trivia lists:** \n\n```" async def trivia_stop(self, ctx):
"""Stops an ongoing trivia session"""
session = self.get_trivia_by_channel(ctx.message.channel)
if session:
await session.end_game()
await self.bot.say("Trivia stopped.")
else:
await self.bot.say("There's no trivia session ongoing in this channel.")
@trivia.group(name="list")
async def trivia_list(self):
"""Shows available trivia lists"""
lists = os.listdir("data/trivia/") lists = os.listdir("data/trivia/")
lists = [l for l in lists if l.endswith(".txt") and " " not in l]
lists = [l.replace(".txt", "") for l in lists]
if lists: if lists:
clean_list = [] msg = "+ Available trivia lists\n\n" + ", ".join(lists)
for txt in lists: msg = box(msg, lang="diff")
if txt.endswith(".txt") and " " not in txt: if len(lists) < 100:
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 += "```"
if len(clean_list) > 100:
await self.bot.send_message(author, msg)
else:
await self.bot.say(msg) await self.bot.say(msg)
else: else:
await self.bot.say("There are no trivia lists available.") await self.bot.whisper(msg)
else: else:
await self.bot.say("There are no trivia lists available.") await self.bot.say("There are no trivia lists available.")
def get_trivia_by_channel(self, channel):
for t in self.trivia_sessions:
if t.channel == channel:
return t
return None
async def on_message(self, message):
if message.author != self.bot.user:
session = self.get_trivia_by_channel(message.channel)
if session:
await session.check_answer(message)
async def on_trivia_end(self, instance):
if instance in self.trivia_sessions:
self.trivia_sessions.remove(instance)
class TriviaSession(): class TriviaSession():
def __init__(self, message, settings): def __init__(self, bot, channel, settings):
self.bot = bot
self.gave_answer = ["I know this one! {}!", "Easy: {}.", "Oh really? It's {} of course."] self.gave_answer = ["I know this one! {}!", "Easy: {}.", "Oh really? It's {} of course."]
self.current_q = None # {"QUESTION" : "String", "ANSWERS" : []} self.current_q = None # {"QUESTION" : "String", "ANSWERS" : []}
self.question_list = "" self.question_list = ""
self.channel = message.channel self.channel = channel
self.score_list = {} self.score_list = {}
self.status = None self.status = None
self.timer = None self.timer = None
self.count = 0 self.count = 0
self.settings = settings self.settings = settings
async def load_questions(self, msg): async def load_questions(self, filename):
msg = msg.split(" ") path = "data/trivia/{}.txt".format(filename)
if len(msg) == 2: if os.path.isfile(path):
_, qlist = msg self.question_list = await self.load_list(path)
if qlist == "random":
chosen_list = randchoice(glob.glob("data/trivia/*.txt"))
self.question_list = self.load_list(chosen_list)
self.status = "new question" self.status = "new question"
self.timeout = time.perf_counter() self.timeout = time.perf_counter()
if self.question_list: await self.new_question() if self.question_list:
await self.new_question()
else: else:
if os.path.isfile("data/trivia/" + qlist + ".txt"): await self.bot.say("There is no list with that name.")
self.question_list = await self.load_list("data/trivia/" + qlist + ".txt")
self.status = "new question"
self.timeout = time.perf_counter()
if self.question_list: await self.new_question()
else:
await trivia_manager.bot.say("There is no list with that name.")
await self.stop_trivia() await self.stop_trivia()
else:
await trivia_manager.bot.say("trivia [list name]")
async def stop_trivia(self): async def stop_trivia(self):
self.status = "stop" self.status = "stop"
trivia_manager.trivia_sessions.remove(self) self.bot.dispatch("trivia_end", self)
async def end_game(self): async def end_game(self):
self.status = "stop" self.status = "stop"
if self.score_list: if self.score_list:
await self.send_table() await self.send_table()
trivia_manager.trivia_sessions.remove(self) self.bot.dispatch("trivia_end", self)
def guess_encoding(self, trivia_list): def guess_encoding(self, trivia_list):
with open(trivia_list, "rb") as f: with open(trivia_list, "rb") as f:
@ -190,21 +187,21 @@ class TriviaSession():
if self.question_list == []: if self.question_list == []:
await self.end_game() await self.end_game()
return True return True
self.current_q = randchoice(self.question_list) self.current_q = choice(self.question_list)
self.question_list.remove(self.current_q) self.question_list.remove(self.current_q)
self.status = "waiting for answer" self.status = "waiting for answer"
self.count += 1 self.count += 1
self.timer = int(time.perf_counter()) self.timer = int(time.perf_counter())
msg = "**Question number {}!**\n\n{}".format(str(self.count), self.current_q["QUESTION"]) msg = "**Question number {}!**\n\n{}".format(str(self.count), self.current_q["QUESTION"])
try: try:
await trivia_manager.bot.say(msg) await self.bot.say(msg)
except: except:
await asyncio.sleep(0.5) await asyncio.sleep(0.5)
await trivia_manager.bot.say(msg) await self.bot.say(msg)
while self.status != "correct answer" and abs(self.timer - int(time.perf_counter())) <= self.settings["TRIVIA_DELAY"]: while self.status != "correct answer" and abs(self.timer - int(time.perf_counter())) <= self.settings["TRIVIA_DELAY"]:
if abs(self.timeout - int(time.perf_counter())) >= self.settings["TRIVIA_TIMEOUT"]: if abs(self.timeout - int(time.perf_counter())) >= self.settings["TRIVIA_TIMEOUT"]:
await trivia_manager.bot.say("Guys...? Well, I guess I'll stop then.") await self.bot.say("Guys...? Well, I guess I'll stop then.")
await self.stop_trivia() await self.stop_trivia()
return True return True
await asyncio.sleep(1) #Waiting for an answer or for the time limit await asyncio.sleep(1) #Waiting for an answer or for the time limit
@ -216,17 +213,17 @@ class TriviaSession():
elif self.status == "stop": elif self.status == "stop":
return True return True
else: else:
msg = randchoice(self.gave_answer).format(self.current_q["ANSWERS"][0]) msg = choice(self.gave_answer).format(self.current_q["ANSWERS"][0])
if self.settings["TRIVIA_BOT_PLAYS"]: if self.settings["TRIVIA_BOT_PLAYS"]:
msg += " **+1** for me!" msg += " **+1** for me!"
self.add_point(trivia_manager.bot.user.name) self.add_point(self.bot.user.name)
self.current_q["ANSWERS"] = [] self.current_q["ANSWERS"] = []
try: try:
await trivia_manager.bot.say(msg) await self.bot.say(msg)
await trivia_manager.bot.send_typing(self.channel) await self.bot.send_typing(self.channel)
except: except:
await asyncio.sleep(0.5) await asyncio.sleep(0.5)
await trivia_manager.bot.say(msg) await self.bot.say(msg)
await asyncio.sleep(3) await asyncio.sleep(3)
if not self.status == "stop": if not self.status == "stop":
await self.new_question() await self.new_question()
@ -240,10 +237,10 @@ class TriviaSession():
t += str(score[1]) # score t += str(score[1]) # score
t += "\n" t += "\n"
t += "```" t += "```"
await trivia_manager.bot.say(t) await self.bot.say(t)
async def check_answer(self, message): async def check_answer(self, message):
if message.author.id != trivia_manager.bot.user.id: if message.author.id != self.bot.user.id:
self.timeout = time.perf_counter() self.timeout = time.perf_counter()
if self.current_q is not None: if self.current_q is not None:
for answer in self.current_q["ANSWERS"]: for answer in self.current_q["ANSWERS"]:
@ -253,11 +250,11 @@ class TriviaSession():
self.add_point(message.author.name) self.add_point(message.author.name)
msg = "You got it {}! **+1** to you!".format(message.author.name) msg = "You got it {}! **+1** to you!".format(message.author.name)
try: try:
await trivia_manager.bot.send_typing(self.channel) await self.bot.send_typing(self.channel)
await trivia_manager.bot.send_message(message.channel, msg) await self.bot.send_message(message.channel, msg)
except: except:
await asyncio.sleep(0.5) await asyncio.sleep(0.5)
await trivia_manager.bot.send_message(message.channel, msg) await self.bot.send_message(message.channel, msg)
return True return True
def add_point(self, user): def add_point(self, user):
@ -266,22 +263,6 @@ class TriviaSession():
else: else:
self.score_list[user] = 1 self.score_list[user] = 1
def get_trivia_question(self):
q = randchoice(list(trivia_questions.keys()))
return q, trivia_questions[q] # question, answer
async def get_trivia_by_channel(channel):
for t in trivia_manager.trivia_sessions:
if t.channel == channel:
return t
return False
async def check_messages(message):
if message.author.id != trivia_manager.bot.user.id:
if await get_trivia_by_channel(message.channel):
trvsession = await get_trivia_by_channel(message.channel)
await trvsession.check_answer(message)
def check_folders(): def check_folders():
folders = ("data", "data/trivia/") folders = ("data", "data/trivia/")
@ -300,9 +281,6 @@ def check_files():
def setup(bot): def setup(bot):
global trivia_manager
check_folders() check_folders()
check_files() check_files()
bot.add_listener(check_messages, "on_message") bot.add_cog(Trivia(bot))
trivia_manager = Trivia(bot)
bot.add_cog(trivia_manager)