4747
4848from ..channel import _threaded_guild_channel_factory
4949from ..enums import Enum as DiscordEnum
50- from ..enums import MessageType , SlashCommandOptionType , try_enum
50+ from ..enums import IntegrationType , InteractionContextType , MessageType , SlashCommandOptionType , try_enum
5151from ..errors import (
5252 ApplicationCommandError ,
5353 ApplicationCommandInvokeError ,
5454 CheckFailure ,
5555 ClientException ,
56+ InvalidArgument ,
5657 ValidationError ,
5758)
5859from ..member import Member
6162from ..role import Role
6263from ..threads import Thread
6364from ..user import User
64- from ..utils import MISSING , async_all , find , maybe_coroutine , utcnow
65+ from ..utils import MISSING , async_all , find , maybe_coroutine , utcnow , warn_deprecated
6566from .context import ApplicationContext , AutocompleteContext
6667from .options import Option , OptionChoice
6768
@@ -226,11 +227,33 @@ def __init__(self, func: Callable, **kwargs) -> None:
226227 "__default_member_permissions__" ,
227228 kwargs .get ("default_member_permissions" , None ),
228229 )
229- self .guild_only : bool | None = getattr (
230- func , "__guild_only__" , kwargs .get ("guild_only" , None )
231- )
232230 self .nsfw : bool | None = getattr (func , "__nsfw__" , kwargs .get ("nsfw" , None ))
233231
232+ integration_types = getattr (
233+ func , "__integration_types__" , kwargs .get ("integration_types" , None )
234+ )
235+ contexts = getattr (
236+ func , "__contexts__" , kwargs .get ("contexts" , None )
237+ )
238+ guild_only = getattr (
239+ func , "__guild_only__" , kwargs .get ("guild_only" , MISSING )
240+ )
241+ if guild_only is not MISSING :
242+ warn_deprecated ("guild_only" , "contexts" , "2.6" )
243+ if contexts and guild_only :
244+ raise InvalidArgument ("cannot pass both 'contexts' and 'guild_only' to ApplicationCommand" )
245+ if self .guild_ids and ((contexts is not None ) or guild_only or integration_types ):
246+ raise InvalidArgument ("the 'contexts' and 'integration_types' parameters are not available for guild commands" )
247+
248+ self .contexts : set [InteractionContextType ] = contexts or {
249+ InteractionContextType .guild ,
250+ InteractionContextType .bot_dm ,
251+ InteractionContextType .private_channel ,
252+ }
253+ if guild_only :
254+ self .guild_only : bool | None = guild_only
255+ self .integration_types : set [IntegrationType ] = integration_types or {IntegrationType .guild_install }
256+
234257 def __repr__ (self ) -> str :
235258 return f"<discord.commands.{ self .__class__ .__name__ } name={ self .name } >"
236259
@@ -274,6 +297,19 @@ def callback(
274297 unwrap = unwrap_function (function )
275298 self .module = unwrap .__module__
276299
300+ @property
301+ def guild_only (self ) -> bool :
302+ warn_deprecated ("guild_only" , "contexts" , "2.6" )
303+ return InteractionContextType .guild in self .contexts and len (self .contexts ) == 1
304+
305+ @guild_only .setter
306+ def guild_only (self , value : bool ) -> None :
307+ warn_deprecated ("guild_only" , "contexts" , "2.6" )
308+ if value :
309+ self .contexts = {InteractionContextType .guild }
310+ else :
311+ self .contexts = {InteractionContextType .guild , InteractionContextType .bot_dm , InteractionContextType .private_channel }
312+
277313 def _prepare_cooldowns (self , ctx : ApplicationContext ):
278314 if self ._buckets .valid :
279315 current = datetime .datetime .now ().timestamp ()
@@ -631,6 +667,9 @@ class SlashCommand(ApplicationCommand):
631667 Returns a string that allows you to mention the slash command.
632668 guild_only: :class:`bool`
633669 Whether the command should only be usable inside a guild.
670+
671+ .. deprecated:: 2.6
672+ Use the ``contexts`` parameter instead.
634673 nsfw: :class:`bool`
635674 Whether the command should be restricted to 18+ channels and users.
636675 Apps intending to be listed in the App Directory cannot have NSFW commands.
@@ -654,6 +693,10 @@ class SlashCommand(ApplicationCommand):
654693 description_localizations: Dict[:class:`str`, :class:`str`]
655694 The description localizations for this command. The values of this should be ``"locale": "description"``.
656695 See `here <https://discord.com/developers/docs/reference#locales>`_ for a list of valid locales.
696+ integration_types: set[:class:`IntegrationType`]
697+ The installation contexts where this command is available. Cannot be set if this is a guild command.
698+ contexts: set[:class:`InteractionContextType`]
699+ The interaction contexts where this command is available. Cannot be set if this is a guild command.
657700 """
658701
659702 type = 1
@@ -881,9 +924,6 @@ def to_dict(self) -> dict:
881924 if self .is_subcommand :
882925 as_dict ["type" ] = SlashCommandOptionType .sub_command .value
883926
884- if self .guild_only is not None :
885- as_dict ["dm_permission" ] = not self .guild_only
886-
887927 if self .nsfw is not None :
888928 as_dict ["nsfw" ] = self .nsfw
889929
@@ -892,6 +932,10 @@ def to_dict(self) -> dict:
892932 self .default_member_permissions .value
893933 )
894934
935+ if not self .guild_ids :
936+ as_dict ["integration_types" ] = [it .value for it in self .integration_types ]
937+ as_dict ["contexts" ] = [ctx .value for ctx in self .contexts ]
938+
895939 return as_dict
896940
897941 async def _invoke (self , ctx : ApplicationContext ) -> None :
@@ -1100,6 +1144,9 @@ class SlashCommandGroup(ApplicationCommand):
11001144 isn't one.
11011145 guild_only: :class:`bool`
11021146 Whether the command should only be usable inside a guild.
1147+
1148+ .. deprecated:: 2.6
1149+ Use the ``contexts`` parameter instead.
11031150 nsfw: :class:`bool`
11041151 Whether the command should be restricted to 18+ channels and users.
11051152 Apps intending to be listed in the App Directory cannot have NSFW commands.
@@ -1118,6 +1165,10 @@ class SlashCommandGroup(ApplicationCommand):
11181165 description_localizations: Dict[:class:`str`, :class:`str`]
11191166 The description localizations for this command. The values of this should be ``"locale": "description"``.
11201167 See `here <https://discord.com/developers/docs/reference#locales>`_ for a list of valid locales.
1168+ integration_types: set[:class:`IntegrationType`]
1169+ The installation contexts where this command is available. Cannot be set if this is a guild command.
1170+ contexts: set[:class:`InteractionContextType`]
1171+ The interaction contexts where this command is available. Cannot be set if this is a guild command.
11211172 """
11221173
11231174 __initial_commands__ : list [SlashCommand | SlashCommandGroup ]
@@ -1174,12 +1225,28 @@ def __init__(
11741225 self .id = None
11751226
11761227 # Permissions
1177- self .default_member_permissions : Permissions | None = kwargs .get (
1178- "default_member_permissions" , None
1179- )
1180- self .guild_only : bool | None = kwargs .get ("guild_only" , None )
1228+ self .default_member_permissions : Permissions | None = kwargs .get ("default_member_permissions" , None )
11811229 self .nsfw : bool | None = kwargs .get ("nsfw" , None )
11821230
1231+ integration_types = kwargs .get ("integration_types" , None )
1232+ contexts = kwargs .get ("contexts" , None )
1233+ guild_only = kwargs .get ("guild_only" , MISSING )
1234+ if guild_only is not MISSING :
1235+ warn_deprecated ("guild_only" , "contexts" , "2.6" )
1236+ if contexts and guild_only :
1237+ raise InvalidArgument ("cannot pass both 'contexts' and 'guild_only' to ApplicationCommand" )
1238+ if self .guild_ids and ((contexts is not None ) or guild_only or integration_types ):
1239+ raise InvalidArgument ("the 'contexts' and 'integration_types' parameters are not available for guild commands" )
1240+
1241+ self .contexts : set [InteractionContextType ] = contexts or {
1242+ InteractionContextType .guild ,
1243+ InteractionContextType .bot_dm ,
1244+ InteractionContextType .private_channel ,
1245+ }
1246+ if guild_only :
1247+ self .guild_only : bool | None = guild_only
1248+ self .integration_types : set [IntegrationType ] = integration_types or {IntegrationType .guild_install }
1249+
11831250 self .name_localizations : dict [str , str ] = kwargs .get (
11841251 "name_localizations" , MISSING
11851252 )
@@ -1218,6 +1285,19 @@ def __init__(
12181285 def module (self ) -> str | None :
12191286 return self .__module__
12201287
1288+ @property
1289+ def guild_only (self ) -> bool :
1290+ warn_deprecated ("guild_only" , "contexts" , "2.6" )
1291+ return InteractionContextType .guild in self .contexts and len (self .contexts ) == 1
1292+
1293+ @guild_only .setter
1294+ def guild_only (self , value : bool ) -> None :
1295+ warn_deprecated ("guild_only" , "contexts" , "2.6" )
1296+ if value :
1297+ self .contexts = {InteractionContextType .guild }
1298+ else :
1299+ self .contexts = {InteractionContextType .guild , InteractionContextType .bot_dm , InteractionContextType .private_channel }
1300+
12211301 def to_dict (self ) -> dict :
12221302 as_dict = {
12231303 "name" : self .name ,
@@ -1232,9 +1312,6 @@ def to_dict(self) -> dict:
12321312 if self .parent is not None :
12331313 as_dict ["type" ] = self .input_type .value
12341314
1235- if self .guild_only is not None :
1236- as_dict ["dm_permission" ] = not self .guild_only
1237-
12381315 if self .nsfw is not None :
12391316 as_dict ["nsfw" ] = self .nsfw
12401317
@@ -1243,6 +1320,10 @@ def to_dict(self) -> dict:
12431320 self .default_member_permissions .value
12441321 )
12451322
1323+ if not self .guild_ids :
1324+ as_dict ["integration_types" ] = [it .value for it in self .integration_types ]
1325+ as_dict ["contexts" ] = [ctx .value for ctx in self .contexts ]
1326+
12461327 return as_dict
12471328
12481329 def add_command (self , command : SlashCommand ) -> None :
@@ -1476,6 +1557,9 @@ class ContextMenuCommand(ApplicationCommand):
14761557 The ids of the guilds where this command will be registered.
14771558 guild_only: :class:`bool`
14781559 Whether the command should only be usable inside a guild.
1560+
1561+ .. deprecated:: 2.6
1562+ Use the ``contexts`` parameter instead.
14791563 nsfw: :class:`bool`
14801564 Whether the command should be restricted to 18+ channels and users.
14811565 Apps intending to be listed in the App Directory cannot have NSFW commands.
@@ -1496,6 +1580,10 @@ class ContextMenuCommand(ApplicationCommand):
14961580 name_localizations: Dict[:class:`str`, :class:`str`]
14971581 The name localizations for this command. The values of this should be ``"locale": "name"``. See
14981582 `here <https://discord.com/developers/docs/reference#locales>`_ for a list of valid locales.
1583+ integration_types: set[:class:`IntegrationType`]
1584+ The installation contexts where this command is available. Cannot be set if this is a guild command.
1585+ contexts: set[:class:`InteractionContextType`]
1586+ The interaction contexts where this command is available. Cannot be set if this is a guild command.
14991587 """
15001588
15011589 def __new__ (cls , * args , ** kwargs ) -> ContextMenuCommand :
0 commit comments