Add slash_command_guilds to bot and decos

This commit is contained in:
Gnome 2021-09-01 17:00:37 +01:00
parent 6faea43c99
commit f1d7d353b5
2 changed files with 59 additions and 9 deletions

View File

@ -35,11 +35,13 @@ import importlib.util
import sys
import traceback
import types
from typing import Any, Callable, cast, Mapping, List, Dict, TYPE_CHECKING, Optional, TypeVar, Type, Union
from collections import defaultdict
from typing import Any, Callable, Iterable, cast, Mapping, List, Dict, TYPE_CHECKING, Optional, TypeVar, Type, Union
import discord
from discord.types.interactions import (
ApplicationCommandInteractionData,
EditApplicationCommand,
_ApplicationCommandInteractionDataOptionString
)
@ -174,7 +176,7 @@ class BotBase(GroupMixin):
if not (message_commands or slash_commands):
raise TypeError("Both message_commands and slash_commands are disabled.")
elif slash_commands:
self.slash_command_guild = options.get('slash_command_guild', None)
self.slash_command_guilds: Optional[Iterable[int]] = options.get('slash_command_guilds', None)
if help_command is _default:
self.help_command = DefaultHelpCommand()
@ -192,12 +194,44 @@ class BotBase(GroupMixin):
self._schedule_event(event, ev, *args, **kwargs) # type: ignore
async def _create_application_commands(self, application_id: int, http: HTTPClient):
commands = [scmd for cmd in self.commands if not cmd.hidden and (scmd := cmd.to_application_command()) is not None]
commands: defaultdict[Optional[int], List[EditApplicationCommand]] = defaultdict(list)
for command in self.commands:
if command.hidden:
continue
if self.slash_command_guild is None:
await http.bulk_upsert_global_commands(application_id, payload=commands)
else:
await http.bulk_upsert_guild_commands(application_id, self.slash_command_guild, payload=commands)
payload = command.to_application_command()
if payload is None:
continue
guilds = command.slash_command_guilds or self.slash_command_guilds
if guilds is None:
commands[None].append(payload)
else:
for guild in guilds:
commands[guild].append(payload)
global_commands = commands.pop(None, None)
if global_commands is not None:
if self.slash_command_guilds is None:
await http.bulk_upsert_global_commands(
payload=global_commands,
application_id=application_id,
)
else:
for guild in self.slash_command_guilds:
await http.bulk_upsert_guild_commands(
guild_id=guild,
payload=global_commands,
application_id=application_id,
)
for guild, guild_commands in commands.items():
assert guild is not None
await http.bulk_upsert_guild_commands(
guild_id=guild,
payload=guild_commands,
application_id=application_id,
)
@discord.utils.copy_doc(discord.Client.close)
@ -1242,6 +1276,14 @@ class Bot(BotBase, discord.Client):
a :class:`Command` object via the ``slash_command`` parameter
.. versionadded:: 2.0
slash_command_guilds: Optional[:class:`List[int]`]
If this is set, only upload slash commands to these guild IDs.
Can be overwritten per command in the command decorators or when making
a :class:`Command` object via the ``slash_command_guilds`` parameter
.. versionadded:: 2.0
"""
async def setup(self):
if not self.slash_commands:

View File

@ -30,6 +30,7 @@ from typing import (
Dict,
Generator,
Generic,
Iterable,
Literal,
List,
Optional,
@ -296,21 +297,24 @@ class Command(_BaseCommand, Generic[CogT, P, T]):
.. note::
This object may be copied by the library.
message_command: Optional[:class:`bool`]
Whether to process this command based on messages.
This overwrites the global ``message_commands`` parameter of :class:`.Bot`.
.. versionadded:: 2.0
slash_command: Optional[:class:`bool`]
Whether to upload and process this command as a slash command.
This overwrites the global ``slash_commands`` parameter of :class:`.Bot`.
.. versionadded:: 2.0
slash_command_guilds: Optional[:class:`List[int]`]
If this is set, only upload this slash command to these guild IDs.
This overwrites the global ``slash_command_guilds`` parameter of :class:`.Bot`.
.. versionadded:: 2.0
"""
__original_kwargs__: Dict[str, Any]
@ -344,8 +348,10 @@ class Command(_BaseCommand, Generic[CogT, P, T]):
self.callback = func
self.enabled: bool = kwargs.get('enabled', True)
self.slash_command: Optional[bool] = kwargs.get("slash_command", None)
self.message_command: Optional[bool] = kwargs.get("message_command", None)
self.slash_command_guilds: Optional[Iterable[int]] = kwargs.get("slash_command_guilds", None)
help_doc = kwargs.get('help')
if help_doc is not None:
@ -405,6 +411,8 @@ class Command(_BaseCommand, Generic[CogT, P, T]):
# bandaid for the fact that sometimes parent can be the bot instance
parent = kwargs.get('parent')
self.parent: Optional[GroupMixin] = parent if isinstance(parent, _BaseCommand) else None # type: ignore
if self.slash_command_guilds is not None and self.parent is not None:
raise TypeError("Cannot set specific guilds for a subcommand. They are inherited from the top level group.")
self._before_invoke: Optional[Hook] = None
try: