mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 11:18:54 -05:00
[V3] Start work on fuzzy command search (#1600)
* [V3] Start work on fuzzy command search * Implement in command error handler * Something isn't working here, try fixing * Style compliance * Add fuzzywuzzy to pipfile * Dump the short doc part if there is no short doc * Add fuzzy command search on command not found in help * Move things around, implement for use of default d.py help formatter * Formatting compliance * Undo pipfile changes
This commit is contained in:
parent
4028dd3009
commit
4f270f3aab
@ -86,6 +86,9 @@ class RedBase(BotBase):
|
|||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
loop.run_until_complete(self._dict_abuse(kwargs))
|
loop.run_until_complete(self._dict_abuse(kwargs))
|
||||||
|
|
||||||
|
if "command_not_found" not in kwargs:
|
||||||
|
kwargs["command_not_found"] = "Command {} not found.\n{}"
|
||||||
|
|
||||||
self.counter = Counter()
|
self.counter = Counter()
|
||||||
self.uptime = None
|
self.uptime = None
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,8 @@ from discord.ext import commands
|
|||||||
|
|
||||||
from . import __version__
|
from . import __version__
|
||||||
from .data_manager import storage_type
|
from .data_manager import storage_type
|
||||||
from .utils.chat_formatting import inline, bordered
|
from .utils.chat_formatting import inline, bordered, pagify, box
|
||||||
|
from .utils import fuzzy_command_search
|
||||||
from colorama import Fore, Style, init
|
from colorama import Fore, Style, init
|
||||||
|
|
||||||
log = logging.getLogger("red")
|
log = logging.getLogger("red")
|
||||||
@ -221,7 +222,10 @@ def init_events(bot, cli_flags):
|
|||||||
if not hasattr(ctx.cog, "_{0.command.cog_name}__error".format(ctx)):
|
if not hasattr(ctx.cog, "_{0.command.cog_name}__error".format(ctx)):
|
||||||
await ctx.send(inline(message))
|
await ctx.send(inline(message))
|
||||||
elif isinstance(error, commands.CommandNotFound):
|
elif isinstance(error, commands.CommandNotFound):
|
||||||
pass
|
term = ctx.invoked_with + " "
|
||||||
|
if len(ctx.args) > 1:
|
||||||
|
term += " ".join(ctx.args[1:])
|
||||||
|
await ctx.maybe_send_embed(fuzzy_command_search(ctx, ctx.invoked_with))
|
||||||
elif isinstance(error, commands.CheckFailure):
|
elif isinstance(error, commands.CheckFailure):
|
||||||
await ctx.send("⛔ You are not authorized to issue that command.")
|
await ctx.send("⛔ You are not authorized to issue that command.")
|
||||||
elif isinstance(error, commands.NoPrivateMessage):
|
elif isinstance(error, commands.NoPrivateMessage):
|
||||||
|
|||||||
@ -36,7 +36,8 @@ import sys
|
|||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from . import commands
|
from . import commands
|
||||||
from redbot.core.utils.chat_formatting import pagify
|
from redbot.core.utils.chat_formatting import pagify, box
|
||||||
|
from redbot.core.utils import fuzzy_command_search
|
||||||
|
|
||||||
|
|
||||||
EMPTY_STRING = u"\u200b"
|
EMPTY_STRING = u"\u200b"
|
||||||
@ -277,11 +278,9 @@ class Help(formatter.HelpFormatter):
|
|||||||
|
|
||||||
def cmd_not_found(self, ctx, cmd, color=None):
|
def cmd_not_found(self, ctx, cmd, color=None):
|
||||||
# Shortcut for a shortcut. Sue me
|
# Shortcut for a shortcut. Sue me
|
||||||
|
out = fuzzy_command_search(ctx, " ".join(ctx.args[1:]))
|
||||||
embed = self.simple_embed(
|
embed = self.simple_embed(
|
||||||
ctx,
|
ctx, title="Command {} not found.".format(cmd), description=out, color=color
|
||||||
title=ctx.bot.command_not_found.format(cmd),
|
|
||||||
description="Commands are case sensitive. Please check your spelling and try again",
|
|
||||||
color=color,
|
|
||||||
)
|
)
|
||||||
return embed
|
return embed
|
||||||
|
|
||||||
@ -324,7 +323,9 @@ async def help(ctx, *cmds: str):
|
|||||||
if use_embeds:
|
if use_embeds:
|
||||||
await destination.send(embed=ctx.bot.formatter.cmd_not_found(ctx, name))
|
await destination.send(embed=ctx.bot.formatter.cmd_not_found(ctx, name))
|
||||||
else:
|
else:
|
||||||
await destination.send(ctx.bot.command_not_found.format(name))
|
await destination.send(
|
||||||
|
ctx.bot.command_not_found.format(name, fuzzy_command_search(ctx, name))
|
||||||
|
)
|
||||||
return
|
return
|
||||||
if use_embeds:
|
if use_embeds:
|
||||||
embeds = await ctx.bot.formatter.format_help_for(ctx, command)
|
embeds = await ctx.bot.formatter.format_help_for(ctx, command)
|
||||||
@ -337,7 +338,9 @@ async def help(ctx, *cmds: str):
|
|||||||
if use_embeds:
|
if use_embeds:
|
||||||
await destination.send(embed=ctx.bot.formatter.cmd_not_found(ctx, name))
|
await destination.send(embed=ctx.bot.formatter.cmd_not_found(ctx, name))
|
||||||
else:
|
else:
|
||||||
await destination.send(ctx.bot.command_not_found.format(name))
|
await destination.send(
|
||||||
|
ctx.bot.command_not_found.format(name, fuzzy_command_search(ctx, name))
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
for key in cmds[1:]:
|
for key in cmds[1:]:
|
||||||
@ -348,7 +351,9 @@ async def help(ctx, *cmds: str):
|
|||||||
if use_embeds:
|
if use_embeds:
|
||||||
await destination.send(embed=ctx.bot.formatter.cmd_not_found(ctx, key))
|
await destination.send(embed=ctx.bot.formatter.cmd_not_found(ctx, key))
|
||||||
else:
|
else:
|
||||||
await destination.send(ctx.bot.command_not_found.format(key))
|
await destination.send(
|
||||||
|
ctx.bot.command_not_found.format(key, fuzzy_command_search(ctx, name))
|
||||||
|
)
|
||||||
return
|
return
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
if use_embeds:
|
if use_embeds:
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
__all__ = ["TYPE_CHECKING", "NewType", "safe_delete"]
|
__all__ = ["TYPE_CHECKING", "NewType", "safe_delete", "fuzzy_command_search"]
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
from redbot.core import commands
|
||||||
|
from fuzzywuzzy import process
|
||||||
|
from .chat_formatting import box
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
@ -26,3 +29,15 @@ def safe_delete(pth: Path):
|
|||||||
for f in files:
|
for f in files:
|
||||||
os.chmod(os.path.join(root, f), 0o755)
|
os.chmod(os.path.join(root, f), 0o755)
|
||||||
shutil.rmtree(str(pth), ignore_errors=True)
|
shutil.rmtree(str(pth), ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
|
def fuzzy_command_search(ctx: commands.Context, term: str):
|
||||||
|
out = ""
|
||||||
|
for pos, extracted in enumerate(process.extract(term, ctx.bot.walk_commands(), limit=5), 1):
|
||||||
|
out += "{0}. {1.prefix}{2.qualified_name}{3}\n".format(
|
||||||
|
pos,
|
||||||
|
ctx,
|
||||||
|
extracted[0],
|
||||||
|
" - {}".format(extracted[0].short_doc) if extracted[0].short_doc else "",
|
||||||
|
)
|
||||||
|
return box(out, lang="Perhaps you wanted one of these?")
|
||||||
|
|||||||
@ -5,5 +5,6 @@ raven==6.5.0
|
|||||||
colorama==0.3.9
|
colorama==0.3.9
|
||||||
jsonrpcserver
|
jsonrpcserver
|
||||||
pyyaml==3.12
|
pyyaml==3.12
|
||||||
|
fuzzywuzzy[speedup]<=0.16.0
|
||||||
Red-Trivia>=1.1.1
|
Red-Trivia>=1.1.1
|
||||||
async-timeout<3.0.0
|
async-timeout<3.0.0
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user