diff --git a/redbot/core/commands/help.py b/redbot/core/commands/help.py index c47eb21df..847592ae2 100644 --- a/redbot/core/commands/help.py +++ b/redbot/core/commands/help.py @@ -566,13 +566,14 @@ class RedHelpFormatter: """ Sends an error, fuzzy help, or stays quiet based on settings """ - coms = { - c - async for c in self.help_filter_func( + fuzzy_commands = await fuzzy_command_search( + ctx, + help_for, + commands=self.help_filter_func( ctx, ctx.bot.walk_commands(), help_settings=help_settings - ) - } - fuzzy_commands = await fuzzy_command_search(ctx, help_for, commands=coms, min_score=75) + ), + min_score=75, + ) use_embeds = await ctx.embed_requested() if fuzzy_commands: ret = await format_fuzzy_results(ctx, fuzzy_commands, embed=use_embeds) diff --git a/redbot/core/events.py b/redbot/core/events.py index c961bf935..7bd8dd14a 100644 --- a/redbot/core/events.py +++ b/redbot/core/events.py @@ -197,12 +197,9 @@ def init_events(bot, cli_flags): help_settings = await HelpSettings.from_context(ctx) fuzzy_commands = await fuzzy_command_search( ctx, - commands={ - c - async for c in RedHelpFormatter.help_filter_func( - ctx, bot.walk_commands(), help_settings=help_settings - ) - }, + commands=RedHelpFormatter.help_filter_func( + ctx, bot.walk_commands(), help_settings=help_settings + ), ) if not fuzzy_commands: pass diff --git a/redbot/core/utils/_internal_utils.py b/redbot/core/utils/_internal_utils.py index de4a9b518..51d2c4828 100644 --- a/redbot/core/utils/_internal_utils.py +++ b/redbot/core/utils/_internal_utils.py @@ -1,6 +1,7 @@ from __future__ import annotations import asyncio +import collections.abc import json import logging import os @@ -9,7 +10,16 @@ import shutil import tarfile from datetime import datetime from pathlib import Path -from typing import Awaitable, Callable, List, Optional, Set, Union, TYPE_CHECKING +from typing import ( + AsyncIterator, + Awaitable, + Callable, + Iterator, + List, + Optional, + Union, + TYPE_CHECKING, +) import discord from fuzzywuzzy import fuzz, process @@ -51,7 +61,7 @@ async def fuzzy_command_search( ctx: Context, term: Optional[str] = None, *, - commands: Optional[Set[Command]] = None, + commands: Optional[Union[AsyncIterator[Command], Iterator[Command]]] = None, min_score: int = 80, ) -> Optional[List[Command]]: """Search for commands which are similar in name to the one invoked. @@ -66,7 +76,7 @@ async def fuzzy_command_search( term : Optional[str] The name of the invoked command. If ``None``, `Context.invoked_with` will be used instead. - commands : Optional[Set[commands.Command]] + commands : Optional[Union[AsyncIterator[commands.Command], Iterator[commands.Command]]] The commands available to choose from when doing a fuzzy match. When omitted, `Bot.walk_commands` will be used instead. min_score : int @@ -108,10 +118,15 @@ async def fuzzy_command_search( else: return None + if commands is None: + choices = set(ctx.bot.walk_commands()) + elif isinstance(commands, collections.abc.AsyncIterator): + choices = {c async for c in commands} + else: + choices = set(commands) + # Do the scoring. `extracted` is a list of tuples in the form `(command, score)` - extracted = process.extract( - term, (commands or set(ctx.bot.walk_commands())), limit=5, scorer=fuzz.QRatio - ) + extracted = process.extract(term, choices, limit=5, scorer=fuzz.QRatio) if not extracted: return None