Skip to content

Commit 2e485d9

Browse files
SoheabSkelmisooliver1EmmmaTechalentoghostflame
authored
feat(app-cmds): support nsfw only commands (#709)
* Add `nsfw` support for Application commands * Also support message/user commands. * Add missing types in nextcord\types\interactions.py * Fix re-syncing on not consistent discord payload. * add nsfw key to nextcord\types\interactions.py;_ApplicationCommandOptional * Requested changes and versionadded "Not-NSFW channels" -> "Non NSFW channels" Co-Authored-By: Skelmis <[email protected]> * Fix versionadded typo "2.0" -> "2.1" Co-Authored-By: Oliver Wilkes <[email protected]> * docs: bump versionadded to 2.4 * docs: fix phrasing of the nsfw param * docs: fix formatting errors * docs: more formatting errors * correct all descriptions and types * prevent commands from needlessly resyncing More info: #709 (comment) Co-Authored-By: Alex Schoenhofen <[email protected]> --------- Co-authored-by: Skelmis <[email protected]> Co-authored-by: Oliver Wilkes <[email protected]> Co-authored-by: Emre Terzioglu <[email protected]> Co-authored-by: Alex Schoenhofen <[email protected]>
1 parent 68cc92a commit 2e485d9

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

nextcord/application_command.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,6 +1859,7 @@ def __init__(
18591859
guild_ids: Optional[Iterable[int]] = MISSING,
18601860
dm_permission: Optional[bool] = None,
18611861
default_member_permissions: Optional[Union[Permissions, int]] = None,
1862+
nsfw: bool = False,
18621863
parent_cog: Optional[ClientCog] = None,
18631864
force_global: bool = False,
18641865
) -> None:
@@ -1892,6 +1893,10 @@ def __init__(
18921893
Permission(s) required to use the command. Inputting ``8`` or ``Permissions(administrator=True)`` for
18931894
example will only allow Administrators to use the command. If set to 0, nobody will be able to use it by
18941895
default. Server owners CAN override the permission requirements.
1896+
nsfw: :class:`bool`
1897+
Whether the command can only be used in age-restricted channels. Defaults to ``False``.
1898+
1899+
.. versionadded:: 2.4
18951900
parent_cog: Optional[:class:`ClientCog`]
18961901
``ClientCog`` to forward to the callback as the ``self`` argument.
18971902
force_global: :class:`bool`
@@ -1913,6 +1918,7 @@ def __init__(
19131918
self.default_member_permissions: Optional[
19141919
Union[Permissions, int]
19151920
] = default_member_permissions
1921+
self.nsfw: bool = nsfw
19161922

19171923
self.force_global: bool = force_global
19181924

@@ -2114,6 +2120,8 @@ def get_payload(self, guild_id: Optional[int]) -> dict:
21142120
# the default (True) to ensure payload parity for comparisons.
21152121
ret["dm_permission"] = True
21162122

2123+
ret["nsfw"] = self.nsfw
2124+
21172125
return ret
21182126

21192127
def parse_discord_response(
@@ -2175,6 +2183,7 @@ def is_payload_valid(
21752183
"name_localizations",
21762184
"description_localizations",
21772185
"dm_permission",
2186+
"nsfw",
21782187
):
21792188
_log.debug("Failed check dictionary values, not valid payload.")
21802189
return False
@@ -2682,6 +2691,7 @@ def __init__(
26822691
guild_ids: Optional[Iterable[int]] = None,
26832692
dm_permission: Optional[bool] = None,
26842693
default_member_permissions: Optional[Union[Permissions, int]] = None,
2694+
nsfw: bool = False,
26852695
parent_cog: Optional[ClientCog] = None,
26862696
force_global: bool = False,
26872697
) -> None:
@@ -2711,6 +2721,14 @@ def __init__(
27112721
Permission(s) required to use the command. Inputting ``8`` or ``Permissions(administrator=True)`` for
27122722
example will only allow Administrators to use the command. If set to 0, nobody will be able to use it by
27132723
default. Server owners CAN override the permission requirements.
2724+
nsfw: :class:`bool`
2725+
Whether the command can only be used in age-restricted channels. Defaults to ``False``.
2726+
2727+
.. note::
2728+
2729+
Due to a discord limitation, this can only be set for the parent command in case of a subcommand.
2730+
2731+
.. versionadded:: 2.4
27142732
parent_cog: Optional[:class:`ClientCog`]
27152733
``ClientCog`` to forward to the callback as the ``self`` argument.
27162734
force_global: :class:`bool`
@@ -2727,6 +2745,7 @@ def __init__(
27272745
guild_ids=guild_ids,
27282746
default_member_permissions=default_member_permissions,
27292747
dm_permission=dm_permission,
2748+
nsfw=nsfw,
27302749
parent_cog=parent_cog,
27312750
force_global=force_global,
27322751
)
@@ -2846,6 +2865,7 @@ def __init__(
28462865
guild_ids: Optional[Iterable[int]] = None,
28472866
dm_permission: Optional[bool] = None,
28482867
default_member_permissions: Optional[Union[Permissions, int]] = None,
2868+
nsfw: bool = False,
28492869
parent_cog: Optional[ClientCog] = None,
28502870
force_global: bool = False,
28512871
) -> None:
@@ -2870,6 +2890,10 @@ def __init__(
28702890
Permission(s) required to use the command. Inputting ``8`` or ``Permissions(administrator=True)`` for
28712891
example will only allow Administrators to use the command. If set to 0, nobody will be able to use it by
28722892
default. Server owners CAN override the permission requirements.
2893+
nsfw: :class:`bool`
2894+
Whether the command can only be used in age-restricted channels. Defaults to ``False``.
2895+
2896+
.. versionadded:: 2.4
28732897
parent_cog: Optional[:class:`ClientCog`]
28742898
``ClientCog`` to forward to the callback as the ``self`` argument.
28752899
force_global: :class:`bool`
@@ -2884,6 +2908,7 @@ def __init__(
28842908
guild_ids=guild_ids,
28852909
dm_permission=dm_permission,
28862910
default_member_permissions=default_member_permissions,
2911+
nsfw=nsfw,
28872912
parent_cog=parent_cog,
28882913
force_global=force_global,
28892914
)
@@ -2922,6 +2947,7 @@ def __init__(
29222947
guild_ids: Optional[Iterable[int]] = None,
29232948
dm_permission: Optional[bool] = None,
29242949
default_member_permissions: Optional[Union[Permissions, int]] = None,
2950+
nsfw: bool = False,
29252951
parent_cog: Optional[ClientCog] = None,
29262952
force_global: bool = False,
29272953
) -> None:
@@ -2946,6 +2972,10 @@ def __init__(
29462972
Permission(s) required to use the command. Inputting ``8`` or ``Permissions(administrator=True)`` for
29472973
example will only allow Administrators to use the command. If set to 0, nobody will be able to use it by
29482974
default. Server owners CAN override the permission requirements.
2975+
nsfw: :class:`bool`
2976+
Whether the command can only be used in age-restricted channels. Defaults to ``False``.
2977+
2978+
.. versionadded:: 2.4
29492979
parent_cog: Optional[:class:`ClientCog`]
29502980
``ClientCog`` to forward to the callback as the ``self`` argument.
29512981
force_global: :class:`bool`
@@ -2960,6 +2990,7 @@ def __init__(
29602990
guild_ids=guild_ids,
29612991
dm_permission=dm_permission,
29622992
default_member_permissions=default_member_permissions,
2993+
nsfw=nsfw,
29632994
parent_cog=parent_cog,
29642995
force_global=force_global,
29652996
)
@@ -2995,6 +3026,7 @@ def slash_command(
29953026
guild_ids: Optional[Iterable[int]] = MISSING,
29963027
dm_permission: Optional[bool] = None,
29973028
default_member_permissions: Optional[Union[Permissions, int]] = None,
3029+
nsfw: bool = False,
29983030
force_global: bool = False,
29993031
):
30003032
"""Creates a Slash application command from the decorated function.
@@ -3024,6 +3056,14 @@ def slash_command(
30243056
Permission(s) required to use the command. Inputting ``8`` or ``Permissions(administrator=True)`` for
30253057
example will only allow Administrators to use the command. If set to 0, nobody will be able to use it by
30263058
default. Server owners CAN override the permission requirements.
3059+
nsfw: :class:`bool`
3060+
Whether the command can only be used in age-restricted channels. Defaults to ``False``.
3061+
3062+
.. note::
3063+
3064+
Due to a discord limitation, this can only be set for the parent command in case of a subcommand.
3065+
3066+
.. versionadded:: 2.4
30273067
force_global: :class:`bool`
30283068
If True, will force this command to register as a global command, even if ``guild_ids`` is set. Will still
30293069
register to guilds. Has no effect if ``guild_ids`` are never set or added to.
@@ -3042,6 +3082,7 @@ def decorator(func: Callable) -> SlashApplicationCommand:
30423082
guild_ids=guild_ids,
30433083
dm_permission=dm_permission,
30443084
default_member_permissions=default_member_permissions,
3085+
nsfw=nsfw,
30453086
force_global=force_global,
30463087
)
30473088
return app_cmd
@@ -3056,6 +3097,7 @@ def message_command(
30563097
guild_ids: Optional[Iterable[int]] = MISSING,
30573098
dm_permission: Optional[bool] = None,
30583099
default_member_permissions: Optional[Union[Permissions, int]] = None,
3100+
nsfw: bool = False,
30593101
force_global: bool = False,
30603102
):
30613103
"""Creates a Message context command from the decorated function.
@@ -3079,6 +3121,10 @@ def message_command(
30793121
Permission(s) required to use the command. Inputting ``8`` or ``Permissions(administrator=True)`` for
30803122
example will only allow Administrators to use the command. If set to 0, nobody will be able to use it by
30813123
default. Server owners CAN override the permission requirements.
3124+
nsfw: :class:`bool`
3125+
Whether the command can only be used in age-restricted channels. Defaults to ``False``.
3126+
3127+
.. versionadded:: 2.4
30823128
force_global: :class:`bool`
30833129
If True, will force this command to register as a global command, even if ``guild_ids`` is set. Will still
30843130
register to guilds. Has no effect if ``guild_ids`` are never set or added to.
@@ -3095,6 +3141,7 @@ def decorator(func: Callable) -> MessageApplicationCommand:
30953141
guild_ids=guild_ids,
30963142
dm_permission=dm_permission,
30973143
default_member_permissions=default_member_permissions,
3144+
nsfw=nsfw,
30983145
force_global=force_global,
30993146
)
31003147
return app_cmd
@@ -3109,6 +3156,7 @@ def user_command(
31093156
guild_ids: Optional[Iterable[int]] = MISSING,
31103157
dm_permission: Optional[bool] = None,
31113158
default_member_permissions: Optional[Union[Permissions, int]] = None,
3159+
nsfw: bool = False,
31123160
force_global: bool = False,
31133161
):
31143162
"""Creates a User context command from the decorated function.
@@ -3132,6 +3180,10 @@ def user_command(
31323180
Permission(s) required to use the command. Inputting ``8`` or ``Permissions(administrator=True)`` for
31333181
example will only allow Administrators to use the command. If set to 0, nobody will be able to use it by
31343182
default. Server owners CAN override the permission requirements.
3183+
nsfw: :class:`bool`
3184+
Whether the command can only be used in age-restricted channels. Defaults to ``False``.
3185+
3186+
.. versionadded:: 2.4
31353187
force_global: :class:`bool`
31363188
If True, will force this command to register as a global command, even if ``guild_ids`` is set. Will still
31373189
register to guilds. Has no effect if ``guild_ids`` are never set or added to.
@@ -3148,6 +3200,7 @@ def decorator(func: Callable) -> UserApplicationCommand:
31483200
guild_ids=guild_ids,
31493201
dm_permission=dm_permission,
31503202
default_member_permissions=default_member_permissions,
3203+
nsfw=nsfw,
31513204
force_global=force_global,
31523205
)
31533206
return app_cmd

nextcord/client.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2566,6 +2566,7 @@ def user_command(
25662566
guild_ids: Optional[Iterable[int]] = MISSING,
25672567
dm_permission: Optional[bool] = None,
25682568
default_member_permissions: Optional[Union[Permissions, int]] = None,
2569+
nsfw: bool = False,
25692570
force_global: bool = False,
25702571
):
25712572
"""Creates a User context command from the decorated function.
@@ -2588,6 +2589,10 @@ def user_command(
25882589
Permission(s) required to use the command. Inputting ``8`` or ``Permissions(administrator=True)`` for
25892590
example will only allow Administrators to use the command. If set to 0, nobody will be able to use it by
25902591
default. Server owners CAN override the permission requirements.
2592+
nsfw: :class:`bool`
2593+
Whether the command can only be used in age-restricted channels. Defaults to ``False``.
2594+
2595+
.. versionadded:: 2.4
25912596
force_global: :class:`bool`
25922597
If True, will force this command to register as a global command, even if ``guild_ids`` is set. Will still
25932598
register to guilds. Has no effect if ``guild_ids`` are never set or added to.
@@ -2600,6 +2605,7 @@ def decorator(func: Callable):
26002605
guild_ids=guild_ids,
26012606
dm_permission=dm_permission,
26022607
default_member_permissions=default_member_permissions,
2608+
nsfw=nsfw,
26032609
force_global=force_global,
26042610
)(func)
26052611
self._application_commands_to_add.add(result)
@@ -2615,6 +2621,7 @@ def message_command(
26152621
guild_ids: Optional[Iterable[int]] = MISSING,
26162622
dm_permission: Optional[bool] = None,
26172623
default_member_permissions: Optional[Union[Permissions, int]] = None,
2624+
nsfw: bool = False,
26182625
force_global: bool = False,
26192626
):
26202627
"""Creates a Message context command from the decorated function.
@@ -2637,6 +2644,10 @@ def message_command(
26372644
Permission(s) required to use the command. Inputting ``8`` or ``Permissions(administrator=True)`` for
26382645
example will only allow Administrators to use the command. If set to 0, nobody will be able to use it by
26392646
default. Server owners CAN override the permission requirements.
2647+
nsfw: :class:`bool`
2648+
Whether the command can only be used in age-restricted channels. Defaults to ``False``.
2649+
2650+
.. versionadded:: 2.4
26402651
force_global: :class:`bool`
26412652
If True, will force this command to register as a global command, even if ``guild_ids`` is set. Will still
26422653
register to guilds. Has no effect if ``guild_ids`` are never set or added to.
@@ -2665,6 +2676,7 @@ def slash_command(
26652676
description_localizations: Optional[Dict[Union[Locale, str], str]] = None,
26662677
guild_ids: Optional[Iterable[int]] = MISSING,
26672678
dm_permission: Optional[bool] = None,
2679+
nsfw: bool = False,
26682680
default_member_permissions: Optional[Union[Permissions, int]] = None,
26692681
force_global: bool = False,
26702682
):
@@ -2694,6 +2706,10 @@ def slash_command(
26942706
Permission(s) required to use the command. Inputting ``8`` or ``Permissions(administrator=True)`` for
26952707
example will only allow Administrators to use the command. If set to 0, nobody will be able to use it by
26962708
default. Server owners CAN override the permission requirements.
2709+
nsfw: :class:`bool`
2710+
Whether the command can only be used in age-restricted channels. Defaults to ``False``.
2711+
2712+
.. versionadded:: 2.4
26972713
force_global: :class:`bool`
26982714
If True, will force this command to register as a global command, even if ``guild_ids`` is set. Will still
26992715
register to guilds. Has no effect if ``guild_ids`` are never set or added to.
@@ -2708,6 +2724,7 @@ def decorator(func: Callable):
27082724
guild_ids=guild_ids,
27092725
dm_permission=dm_permission,
27102726
default_member_permissions=default_member_permissions,
2727+
nsfw=nsfw,
27112728
force_global=force_global,
27122729
)(func)
27132730
self._application_commands_to_add.add(result)

nextcord/types/interactions.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,22 @@ class ApplicationCommand(TypedDict):
2626
application_id: Snowflake
2727
name: str
2828
description: str
29+
default_member_permissions: str
2930
version: Snowflake
3031
type: NotRequired[ApplicationCommandType]
3132
guild_id: NotRequired[Snowflake]
3233
options: NotRequired[List[ApplicationCommandOption]]
3334
default_permission: NotRequired[bool]
35+
dm_permission: NotRequired[bool]
36+
nsfw: NotRequired[bool]
37+
name_localizations: NotRequired[Dict[str, str]]
38+
description_localizations: NotRequired[Dict[str, str]]
3439

3540

3641
class ApplicationCommandOptionChoice(TypedDict):
3742
name: str
3843
value: Union[str, int, float]
44+
name_localizations: Dict[str, str]
3945

4046

4147
ApplicationCommandOptionType = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
@@ -54,6 +60,8 @@ class ApplicationCommandOption(TypedDict):
5460
min_length: NotRequired[int]
5561
max_length: NotRequired[int]
5662
autocomplete: NotRequired[bool]
63+
name_localizations: NotRequired[Dict[str, str]]
64+
description_localizations: NotRequired[Dict[str, str]]
5765

5866

5967
ApplicationCommandPermissionType = Literal[1, 2]

0 commit comments

Comments
 (0)