didier/cogs/faq.py

179 lines
6.7 KiB
Python

from data import constants
from decorators import help
import discord
from discord.ext import commands
from enums.help_categories import Category
from functions import stringFormatters, checks
from functions.database import faq
class Faq(commands.Cog):
def __init__(self, client):
self.client = client
# Don't allow any commands to work when locked
def cog_check(self, ctx):
return not self.client.locked
@commands.group(name="FAQ", usage="[Categorie]* [@Personen]*", case_insensitive=True, invoke_without_command=True)
@help.Category(category=Category.Other)
async def faq(self, ctx, *args):
"""
Command group that controls the FAQ commands.
When this command is invoked, it sends a list of valid categories.
After invoking in a subject's channel (without passing a category),
it sends the FAQ for that subject instead.
:param ctx: Discord Context
:param args: args passed
"""
# A category was requested
# This is not the cleanest but 80 subcommands is a bit much
if len(args) != 0 and any("@" not in arg for arg in args):
return await self.faqCategory(ctx, args)
# Check if the command was used in a subject's channel
if ctx.channel.id in constants.faq_channels:
return await self.faqCategory(ctx, (constants.faq_channels[ctx.channel.id],))
# List of all categories with the first letter capitalized
resp = [stringFormatters.title_case(cat[0]) for cat in faq.getCategories()]
# Sort alphabetically
resp.sort()
# Create an embed with all the categories
embed = discord.Embed(colour=discord.Colour.blue())
embed.set_author(name="FAQ Categorieën")
embed.description = "\n".join(resp)
# Check if the embed has to be sent to the user
# or if the user tagged anyone
if len(ctx.message.mentions) == 0:
await ctx.author.send(embed=embed)
else:
embed.set_footer(text="Doorgestuurd door {}".format(ctx.author.display_name))
# Send it to everyone that was mentioned
for person in ctx.message.mentions:
if not person.bot:
await person.send(embed=embed)
@faq.command(hidden=True, name="Add", usage="[Category] [Question]* [Answer]*")
@commands.check(checks.isMe)
async def add(self, ctx, category, question=None, answer=None, answer_markdown=None):
"""
Command to add a FAQ to the database
:param ctx: Discord Context
:param category: the category to add the FAQ to
:param question: the question
:param answer: the answer
:param answer_markdown: a version of the answer with markdown applied
"""
# Add a new category
if question is None or answer is None:
faq.addCategory(category)
await ctx.send("**{}** is toegevoegd.".format(category))
else:
# Add a new question/answer couple to a category
faq.addQuestion(category, question, answer, answer_markdown)
await ctx.send("``{}\n{}`` is toegevoegd in {}.".format(question, answer, category))
# Quotes a specific line of the fac instead of DM'ing the entire thing
@faq.command(name="Quote", aliases=["Q"], usage="[Categorie] [Index]")
@help.Category(category=Category.Other)
async def quote(self, ctx, category, index):
"""
Command that quotes 1 line of the FAQ into the current channel.
:param ctx: Discord Context
:param category: the category of the FAQ
:param index: the index in the list to quote
:return:y
"""
# Check if a (valid) number was passed
try:
index = int(index)
if index < 1:
raise ValueError
except ValueError:
await ctx.send("Dit is geen geldig getal.")
# Create a list of categories
categories = [t[0] for t in faq.getCategories()]
# Check if a valid category was passed
if category.lower() not in categories:
return await ctx.send("Dit is geen geldige categorie.")
resp = faq.getCategory(category.lower())
# Check if this index exists in this category
if len(resp) < index:
return await ctx.send("Dit is geen geldig getal.")
# Sort by entry Id
resp.sort(key=lambda x: int(x[0]))
await ctx.send("**{}**\n{}".format(resp[index - 1][2], resp[index - 1][3]))
async def faqCategory(self, ctx, args):
"""
Function that sends everything from a category.
:param ctx: Discord Context
:param args: the args passed
"""
# Create a list of categories
categories = [t[0] for t in faq.getCategories()]
# Random word was passed as a category
if not any(arg.lower() in categories for arg in args):
return await self.sendErrorEmbed(ctx, "Dit is geen geldige categorie.")
elif len(args) - len(ctx.message.mentions) != 1:
# Multiple categories were requested, which is not allowed
return await self.sendErrorEmbed(ctx, "Controleer je argumenten.")
category = ""
# Find the category the user requested
for word in args:
if word.lower() in categories:
category = word
break
resp = faq.getCategory(category.lower())
# Sort by entry Id
resp.sort(key=lambda x: int(x[0]))
embed = discord.Embed(colour=discord.Colour.blue())
embed.set_author(name="FAQ {}".format(stringFormatters.title_case(category)))
# Add everything into the embed
for i, pair in enumerate(resp):
# Add custom markdown if it exists
embed.add_field(name="#{}: {}".format(str(i + 1), pair[2]), value=pair[3] if pair[4] is None else pair[4], inline=False)
# Check if anyone was tagged to send the embed to
if len(ctx.message.mentions) == 0:
await ctx.author.send(embed=embed)
else:
embed.set_footer(text="Doorgestuurd door {}".format(ctx.author.display_name))
# Author tagged some people to send it to
for person in ctx.message.mentions:
await person.send(embed=embed)
async def sendErrorEmbed(self, ctx, message: str):
"""
Function that sends an error embed.
:param ctx: Discord Context
:param message: the message to put in the embed
"""
embed = discord.Embed(colour=discord.Colour.red())
embed.set_author(name="Error")
embed.description = message
await ctx.send(embed=embed)
def setup(client):
client.add_cog(Faq(client))