didier/cogs/help.py

224 lines
8.8 KiB
Python

from data import constants
import discord
from discord.commands import SlashCommand
from discord.ext import commands
from enums.help_categories import categories, getCategory, Category
import json
class HelpCommand(commands.MinimalHelpCommand):
def __init__(self, **options):
super().__init__(**options)
self.ctx = None
self.target = None
self.is_mod = False
# Slightly modifying the original callback in order to
# allow sending help to DM's & checking for Enums
# while removing cog help & checking for mentions
async def command_callback(self, ctx, *, command=None):
self.ctx = ctx
self.is_mod = str(ctx.author.id) == constants.myId
bot = ctx.bot
if ctx.bot.locked:
return
# If mention prefix was used, don't count it as a target
if ctx.message.content.startswith("<@"):
ctx.message.mentions = ctx.message.mentions[1:]
if len(ctx.message.mentions) > 5:
return await ctx.send("Je kan Help maar naar maximaal 5 mensen doorsturen.")
# Send help categories
if command is None:
return await self.send_bot_help(self.get_bot_mapping())
# Check if command is a category
if command.lower() == "mod" and not self.is_mod:
return await self.send_error_message("Je hebt geen toegang tot deze commando's.")
category = getCategory(command, self.is_mod)
if category:
return await self.send_category_help(category)
# Cut the mentions out & split based on subcommand
spl = command.split(" ")
spl = spl[:len(spl) - len(self.ctx.message.mentions)]
# A person was mentioned without passing an argument
if not spl:
return await self.send_bot_help(self.get_bot_mapping())
# Turn dic to lowercase to allow proper name searching
all_commands = {}
for k, v in bot.all_commands.items():
if k is None or v is None:
continue
if isinstance(v, SlashCommand):
continue
all_commands[k.lower()] = v
if spl[0].lower() not in all_commands:
return await self.send_error_message(await self.command_not_found(spl[0]))
cmd = all_commands[spl[0].lower()]
# Check if the entered command path exists
for key in spl[1:]:
try:
all_commands = dict((k.lower(), v) for k, v in cmd.all_commands.items())
if key.lower() not in all_commands:
raise AttributeError
found = all_commands[key.lower()]
except AttributeError:
return await self.send_error_message(await self.subcommand_not_found(cmd, key))
cmd = found
# Subcommands should have the parent command's category
temp = cmd
while temp.parent is not None:
temp = temp.parent
# Don't allow non-mods to see mod commands
try:
if temp.callback.category == Category.Mod and not self.is_mod:
return await self.send_error_message("Je hebt geen toegang tot dit commando.")
except AttributeError:
return await self.send_error_message("Dit is geen (openbaar) commando.")
if isinstance(cmd, commands.Group):
return await self.send_group_help(cmd)
else:
return await self.send_command_help(cmd)
def get_bot_mapping(self):
return categories(self.is_mod)
# Sends list of commands in a category
async def send_category_help(self, category):
# Get a list of all commands in this category
category_commands = [command.name if not command.callback.unpack else command
for command in self.ctx.bot.commands
if hasattr(command.callback, "category") and command.callback.category == category]
# Unpack any groups that have to be unpacked
for command in list(category_commands):
if not isinstance(command, str):
category_commands.remove(command)
category_commands.extend([self.get_name(c) for c in self.unpack_group(command)])
embed = self.create_help_embed(category.value)
embed.add_field(name="Commands", value="\n".join(sorted(category_commands)))
for person in await self.get_destination():
await person.send(embed=embed)
async def send_bot_help(self, mapping):
embed = self.create_help_embed("Help")
embed.add_field(name="Categorieën", value="\n".join(sorted(mapping)))
await self.ctx.send(embed=embed)
async def send_command_help(self, command):
with open("files/help.json", "r") as fp:
helpFile = json.load(fp)
try:
helpDescription = helpFile[self.get_name(command).lower()]
except KeyError:
helpDescription = "Indien je dit leest is DJ STIJN vergeten om dit commando in de help page te zetten. Stuur hem een DM om hem eraan te herinneren."
embed = self.create_help_embed("Help")
embed.add_field(name=await self.get_command_signature(command),
value=await self.add_aliases_formatting(sorted(command.aliases)) + helpDescription)
for person in await self.get_destination():
# Can't send to bots
if person.bot:
continue
await person.send(embed=embed)
async def send_group_help(self, group):
with open("files/help.json", "r") as fp:
helpFile = json.load(fp)
embed = self.create_help_embed(group.name + " Commando's")
try:
helpDescription = helpFile[self.get_name(group).lower()]
except KeyError:
helpDescription = "Indien je dit leest is DJ STIJN vergeten om dit commando in de help page te zetten. Stuur hem een DM om hem eraan te herinneren."
embed.add_field(name=await self.get_command_signature(group),
value=await self.add_aliases_formatting(sorted(group.aliases)) + helpDescription,
inline=False)
# Signature: Aliases - Usage
for subcommand in self.unpack_group(group):
embed.add_field(name=await self.get_command_signature(subcommand),
value=await self.add_aliases_formatting(sorted(subcommand.aliases)) +
helpFile[self.get_name(subcommand).lower()], inline=False)
for person in await self.get_destination():
# Can't send to bots
if person.bot:
continue
await person.send(embed=embed)
# Allow mentioning people to send it to them instead
async def get_destination(self):
if self.ctx.message.mentions:
return set(mention for mention in self.ctx.message.mentions if not mention.bot)
return [self.ctx.author]
async def command_not_found(self, string):
return "Er bestaat geen commando met de naam **{}**".format(string)
async def subcommand_not_found(self, command, string):
return "**{}** heeft geen subcommando met de naam **{}**.".format(command.name, string)
async def get_command_signature(self, command):
return "{} {}".format(self.get_name(command), command.usage if command.usage is not None else "")
async def add_aliases_formatting(self, aliases):
return "*Alias: {}*\n".format(", ".join(aliases)) if aliases else ""
async def send_error_message(self, error):
embed = discord.Embed(colour=discord.Colour.red())
embed.set_author(name="Help")
embed.add_field(name="Error", value=error)
await self.ctx.author.send(embed=embed)
def unpack_group(self, group):
# Create a list of all command objects in this group, in case they aren't hidden, sorted by name
subcommands = [group.all_commands.get(command) for command in group.all_commands]
subcommands.sort(key=lambda x: x.name)
subcommands = filter(lambda x: not x.hidden, subcommands)
return list(set(subcommands))
def get_name(self, command):
return command.qualified_name if command.parents else command.name
def create_help_embed(self, title):
embed = discord.Embed(colour=discord.Colour.blue())
embed.set_author(name=title)
embed.set_footer(text="Syntax: Didier Help [Categorie] of Didier Help [Commando]")
return embed
class Help(commands.Cog):
def __init__(self, client):
self.client = client
self._original_help_command = client.help_command
client.help_command = HelpCommand(command_attrs={"aliases": ["rtfm"]})
client.help_command.cog = self
def cog_unload(self):
self.client.help_command = self._original_help_command
def setup(client):
client.add_cog(Help(client))