Skip to content

Commit

Permalink
Slight reorganisation and implement custom converters for slash commands
Browse files Browse the repository at this point in the history
  • Loading branch information
tandemdude committed Dec 12, 2022
1 parent ec011df commit 83f43c9
Show file tree
Hide file tree
Showing 14 changed files with 86 additions and 176 deletions.
133 changes: 0 additions & 133 deletions TODO.md

This file was deleted.

6 changes: 6 additions & 0 deletions docs/source/api_references/parser.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
====================
Parser API Reference
====================

.. automodule:: lightbulb.parser
:members:
8 changes: 0 additions & 8 deletions docs/source/api_references/utils.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,6 @@ Pag

----

Parser
======

.. automodule:: lightbulb.utils.parser
:members:

----

Permissions
===========

Expand Down
11 changes: 11 additions & 0 deletions docs/source/changelogs/v2-changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ Below are all the changelogs for the stable versions of hikari-lightbulb (versio

----

Version 2.3.2
=============

**Potentially Breaking Changes**

- Module ``lightbulb.utils.parser`` has been moved up a level to ``lightbulb.parser``.

**Other Changes**

- Slash commands now have full custom converter support.

Version 2.3.1
=============

Expand Down
6 changes: 6 additions & 0 deletions docs/source/guides/commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,12 @@ Acceptable primitives: ``str``, ``int``, ``float``

- ``hikari.Attachment`` - ``hikari.OptionType.ATTACHMENT``

.. note::
Slash command options that resolve to type ``hikari.OptionType.STRING`` will also have the appropriate
converter run upon invocation. If this causes the command to take too long to run then you can
pass ``auto_defer=True`` to the ``lightbulb.command`` decorator. The deferral will be processed prior
to the conversion of options.

----

Adding Checks to Commands
Expand Down
7 changes: 6 additions & 1 deletion lightbulb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"BangBangCooldownAlgorithm",
"BaseConverter",
"BaseHelpCommand",
"BaseParser",
"BooleanConverter",
"BotApp",
"BotMissingRequiredPermission",
Expand Down Expand Up @@ -82,6 +83,7 @@
"OptionLike",
"OptionModifier",
"OptionsProxy",
"Parser",
"Plugin",
"PrefixCommand",
"PrefixCommandCompletionEvent",
Expand Down Expand Up @@ -150,6 +152,7 @@
"nsfw_channel_only",
"option",
"owner_only",
"parser",
"plugins",
"set_help",
"set_max_concurrency",
Expand All @@ -170,6 +173,7 @@
from lightbulb import errors
from lightbulb import events
from lightbulb import help_command
from lightbulb import parser
from lightbulb import plugins
from lightbulb import utils
from lightbulb.app import *
Expand All @@ -184,6 +188,7 @@
from lightbulb.errors import *
from lightbulb.events import *
from lightbulb.help_command import *
from lightbulb.parser import *
from lightbulb.plugins import *

__version__ = "2.3.1"
__version__ = "2.3.2"
3 changes: 1 addition & 2 deletions lightbulb/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
from importlib import util

import hikari
from hikari.internal import ux
from multidict import CIMultiDict

from lightbulb import checks
Expand All @@ -44,9 +43,9 @@
from lightbulb import events
from lightbulb import help_command as help_command_
from lightbulb import internal
from lightbulb import parser
from lightbulb import plugins as plugins_
from lightbulb.utils import data_store
from lightbulb.utils import parser

_LOGGER = logging.getLogger("lightbulb.app")
_APPLICATION_CMD_ERROR_REGEX: re.Pattern[str] = re.compile(
Expand Down
2 changes: 1 addition & 1 deletion lightbulb/commands/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
from lightbulb import context as context_
from lightbulb import cooldowns
from lightbulb import events
from lightbulb import parser as parser_
from lightbulb import plugins
from lightbulb.utils import parser as parser_

_AutocompleteableOptionT = t.Union[str, int, float]
AutocompleteCallbackT = t.TypeVar(
Expand Down
2 changes: 1 addition & 1 deletion lightbulb/context/prefix.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

from lightbulb import app as app_
from lightbulb import commands
from lightbulb.utils import parser
from lightbulb import parser


class PrefixContext(base.Context):
Expand Down
20 changes: 19 additions & 1 deletion lightbulb/context/slash.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@

__all__ = ["SlashContext"]

import asyncio
import typing as t

import hikari

from lightbulb import commands
from lightbulb.context import base
from lightbulb.converters import CONVERTER_TYPE_MAPPING

if t.TYPE_CHECKING:
from lightbulb import app as app_
Expand All @@ -41,16 +43,24 @@ class SlashContext(base.ApplicationContext):
command (:obj:`~.commands.slash.SlashCommand`): The command that the context is for.
"""

__slots__ = ("_options", "_raw_options")
__slots__ = ("_options", "_raw_options", "_to_convert")

def __init__(
self, app: app_.BotApp, event: hikari.InteractionCreateEvent, command: commands.slash.SlashCommand
) -> None:
super().__init__(app, event, command)
self._options: t.Dict[str, t.Any] = {}
self._raw_options: t.Sequence[hikari.CommandInteractionOption] = self.interaction.options or []
self._to_convert: t.List[t.Coroutine[t.Any, t.Any, None]] = []
self._parse_options(self.interaction.options)

async def _convert_option(self, name: str, value: str) -> None:
cmd = self.invoked or self.command
if cmd.options[name].arg_type in CONVERTER_TYPE_MAPPING:
self._options[name] = await CONVERTER_TYPE_MAPPING[cmd.options[name].arg_type](self).convert(value)
return
self._options[name] = value

def _parse_options(self, options: t.Optional[t.Sequence[hikari.CommandInteractionOption]]) -> None:
# We need to clear the options here to ensure the subcommand name does not exist in the mapping
self._options.clear()
Expand All @@ -69,12 +79,20 @@ def _parse_options(self, options: t.Optional[t.Sequence[hikari.CommandInteractio
val = t.cast(hikari.Snowflake, int(opt.value) if isinstance(opt.value, str) else opt.value)
self._options[opt.name] = self.resolved.attachments.get(val, opt.value)
else:
if isinstance(opt.value, str):
self._to_convert.append(self._convert_option(opt.name, opt.value))
continue
self._options[opt.name] = opt.value

cmd = self.invoked or self.command
for opt in cmd.options.values():
self._options.setdefault(opt.name, opt.default if opt.default is not hikari.UNDEFINED else None)

async def _maybe_defer(self) -> None:
await super()._maybe_defer()
# Ensure that running converters don't block the automatic deferral
await asyncio.gather(*self._to_convert)

@property
def raw_options(self) -> t.Dict[str, t.Any]:
return self._options
Expand Down
24 changes: 24 additions & 0 deletions lightbulb/converters/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,31 @@
"UserConverter",
]

import datetime
import typing as t

import hikari

from lightbulb.converters import base
from lightbulb.converters import special
from lightbulb.converters.base import *
from lightbulb.converters.special import *

CONVERTER_TYPE_MAPPING: t.Mapping[t.Any, t.Type[base.BaseConverter[t.Any]]] = {
hikari.User: special.UserConverter,
hikari.Member: special.MemberConverter,
hikari.GuildChannel: special.GuildChannelConverter,
hikari.TextableGuildChannel: special.TextableGuildChannelConverter,
hikari.TextableChannel: special.TextableGuildChannelConverter,
hikari.GuildCategory: special.GuildCategoryConverter,
hikari.GuildVoiceChannel: special.GuildVoiceChannelConverter,
hikari.Role: special.RoleConverter,
hikari.Emoji: special.EmojiConverter,
hikari.Guild: special.GuildConverter,
hikari.Message: special.MessageConverter,
hikari.Invite: special.InviteConverter,
hikari.Colour: special.ColourConverter,
hikari.Color: special.ColourConverter,
hikari.Snowflake: special.SnowflakeConverter,
datetime.datetime: special.TimestampConverter,
}
5 changes: 3 additions & 2 deletions lightbulb/converters/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
import abc
import typing as t

from lightbulb import context as context_
if t.TYPE_CHECKING:
from lightbulb import context as context_

T = t.TypeVar("T")

Expand All @@ -38,7 +39,7 @@ class BaseConverter(abc.ABC, t.Generic[T]):
__slots__ = ("context",)

def __init__(self, context: context_.base.Context) -> None:
self.context = context
self.context: context_.Context = context
"""Context to convert the argument(s) under."""

@abc.abstractmethod
Expand Down

0 comments on commit 83f43c9

Please sign in to comment.