Skip to content

Commit

Permalink
feat: Add optional filter parameter to utils.basic_autocomplete (#2590)
Browse files Browse the repository at this point in the history
Signed-off-by: Jeffrey Ruan <[email protected]>
Signed-off-by: plun1331 <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: JustaSqu1d <[email protected]>
Co-authored-by: plun1331 <[email protected]>
  • Loading branch information
4 people authored Sep 28, 2024
1 parent a2117ad commit d39caa0
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ These changes are available on the `master` branch, but have not yet been releas
`tags`. ([#2520](https://github.com/Pycord-Development/pycord/pull/2520))
- Added `Member.guild_banner` and `Member.display_banner` properties.
([#2556](https://github.com/Pycord-Development/pycord/pull/2556))
- Added optional `filter` parameter to `utils.basic_autocomplete()`.
([#2590](https://github.com/Pycord-Development/pycord/pull/2590))

### Fixed

Expand Down
48 changes: 38 additions & 10 deletions discord/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1306,9 +1306,12 @@ def generate_snowflake(dt: datetime.datetime | None = None) -> int:
AV = Awaitable[V]
Values = Union[V, Callable[[AutocompleteContext], Union[V, AV]], AV]
AutocompleteFunc = Callable[[AutocompleteContext], AV]
FilterFunc = Callable[[AutocompleteContext, Any], Union[bool, Awaitable[bool]]]


def basic_autocomplete(values: Values) -> AutocompleteFunc:
def basic_autocomplete(
values: Values, *, filter: FilterFunc | None = None
) -> AutocompleteFunc:
"""A helper function to make a basic autocomplete for slash commands. This is a pretty standard autocomplete and
will return any options that start with the value from the user, case-insensitive. If the ``values`` parameter is
callable, it will be called with the AutocompleteContext.
Expand All @@ -1320,18 +1323,21 @@ def basic_autocomplete(values: Values) -> AutocompleteFunc:
values: Union[Union[Iterable[:class:`.OptionChoice`], Iterable[:class:`str`], Iterable[:class:`int`], Iterable[:class:`float`]], Callable[[:class:`.AutocompleteContext`], Union[Union[Iterable[:class:`str`], Iterable[:class:`int`], Iterable[:class:`float`]], Awaitable[Union[Iterable[:class:`str`], Iterable[:class:`int`], Iterable[:class:`float`]]]]], Awaitable[Union[Iterable[:class:`str`], Iterable[:class:`int`], Iterable[:class:`float`]]]]
Possible values for the option. Accepts an iterable of :class:`str`, a callable (sync or async) that takes a
single argument of :class:`.AutocompleteContext`, or a coroutine. Must resolve to an iterable of :class:`str`.
filter: Optional[Callable[[:class:`.AutocompleteContext`, Any], Union[:class:`bool`, Awaitable[:class:`bool`]]]]
An optional callable (sync or async) used to filter the autocomplete options. It accepts two arguments:
the :class:`.AutocompleteContext` and an item from ``values`` iteration treated as callback parameters. If ``None`` is provided, a default filter is used that includes items whose string representation starts with the user's input value, case-insensitive.
.. versionadded:: 2.7
Returns
-------
Callable[[:class:`.AutocompleteContext`], Awaitable[Union[Iterable[:class:`.OptionChoice`], Iterable[:class:`str`], Iterable[:class:`int`], Iterable[:class:`float`]]]]
A wrapped callback for the autocomplete.
Note
----
Autocomplete cannot be used for options that have specified choices.
Examples
--------
Example
-------
Basic usage:
.. code-block:: python3
Expand All @@ -1344,7 +1350,17 @@ async def autocomplete(ctx):
Option(str, "name", autocomplete=basic_autocomplete(autocomplete))
With filter parameter:
.. code-block:: python3
Option(str, "color", autocomplete=basic_autocomplete(("red", "green", "blue"), filter=lambda c, i: str(c.value or "") in i))
.. versionadded:: 2.0
Note
----
Autocomplete cannot be used for options that have specified choices.
"""

async def autocomplete_callback(ctx: AutocompleteContext) -> V:
Expand All @@ -1355,11 +1371,23 @@ async def autocomplete_callback(ctx: AutocompleteContext) -> V:
if asyncio.iscoroutine(_values):
_values = await _values

def check(item: Any) -> bool:
item = getattr(item, "name", item)
return str(item).lower().startswith(str(ctx.value or "").lower())
if filter is None:

def _filter(ctx: AutocompleteContext, item: Any) -> bool:
item = getattr(item, "name", item)
return str(item).lower().startswith(str(ctx.value or "").lower())

gen = (val for val in _values if _filter(ctx, val))

elif asyncio.iscoroutinefunction(filter):
gen = (val for val in _values if await filter(ctx, val))

elif callable(filter):
gen = (val for val in _values if filter(ctx, val))

else:
raise TypeError("``filter`` must be callable.")

gen = (val for val in _values if check(val))
return iter(itertools.islice(gen, 25))

return autocomplete_callback
Expand Down

0 comments on commit d39caa0

Please sign in to comment.