Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions discord/app_commands/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,8 @@ def to_dict(self) -> ApplicationCommandPayload:
'description': self.description,
'name_localizations': {str(k): v for k, v in self.name_localizations.items()},
'description_localizations': {str(k): v for k, v in self.description_localizations.items()},
'contexts': self.allowed_contexts.to_array() if self.allowed_contexts is not None else None,
'integration_types': self.allowed_installs.to_array() if self.allowed_installs is not None else None,
'contexts': self.allowed_contexts.to_array() if self.allowed_contexts else None,
'integration_types': self.allowed_installs.to_array() if self.allowed_installs else None,
'options': [opt.to_dict() for opt in self.options],
} # type: ignore # Type checker does not understand this literal.

Expand Down Expand Up @@ -394,6 +394,41 @@ async def edit(
)
return AppCommand(data=data, state=state)

async def sync(
self,
) -> AppCommand:
"""|coro|

Syncs the application command to Discord.

.. versionadded:: 2.6

Raises
-------
HTTPException
Syncing the commands failed.
Forbidden
The client does not have the ``applications.commands`` scope in the guild.
MissingApplicationID
The client does not have an application ID.

Returns
--------
:class:`AppCommand`
The application command that got synced.
"""
state = self._state
if not state.application_id:
raise MissingApplicationID

payload = self.to_dict()
if self.guild_id:
data = await state.http.upsert_guild_command(state.application_id, self.guild_id, payload=payload)
else:
data = await state.http.upsert_global_command(state.application_id, payload=payload)

return AppCommand(data=data, state=state)

async def fetch_permissions(self, guild: Snowflake) -> GuildAppCommandPermissions:
"""|coro|

Expand Down
66 changes: 66 additions & 0 deletions discord/app_commands/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -1136,6 +1136,72 @@ async def sync(self, *, guild: Optional[Snowflake] = None) -> List[AppCommand]:

return [AppCommand(data=d, state=self._state) for d in data]

async def sync_command(
self, command: Union[AppCommand, Command, ContextMenu, Group], *, guild: Optional[Snowflake] = None
) -> AppCommand:
"""|coro|

Syncs a single application command to Discord.

.. note ::
This is not recommended for use in most cases, use :meth:`.sync` instead.

.. versionadded:: 2.6

Parameters
-----------
command: Union[:class:`AppCommand`, :class:`Command`, :class:`ContextMenu`, :class:`Group`]
The application command to sync.
If this is an :class:`AppCommand`, it will call its :meth:`AppCommand.sync` method.
guild: Optional[:class:`~discord.abc.Snowflake`]
The guild to sync the command in. If not provided, the command is synced globally.
This is not applicable for :class:`AppCommand` instances, as they are already guild-
specific.

Raises
-------
HTTPException
Syncing the commands failed.
CommandSyncFailure
Syncing the commands failed due to a user related error, typically because
the command has invalid data. This is equivalent to an HTTP status code of
400.
Forbidden
The client does not have the ``applications.commands`` scope in the guild.
MissingApplicationID
The client does not have an application ID.
TranslationError
An error occurred while translating the commands.

Returns
--------
:class:`AppCommand`
The application command that got synced.
"""
if isinstance(command, AppCommand):
return await command.sync()

if self.client.application_id is None:
raise MissingApplicationID

translator = self.translator
if translator:
payload = await command.get_translated_payload(self, translator)
else:
payload = command.to_dict(self)

try:
if guild is None:
data = await self._http.upsert_global_command(self.client.application_id, payload=payload) # type: ignore
else:
data = await self._http.upsert_guild_command(self.client.application_id, guild.id, payload=payload) # type: ignore
except HTTPException as e:
if e.status == 400 and e.code == 50035:
raise CommandSyncFailure(e, [command]) from None
raise

return AppCommand(data=data, state=self._state)

async def _dispatch_error(self, interaction: Interaction[ClientT], error: AppCommandError, /) -> None:
command = interaction.command
interaction.command_failed = True
Expand Down
2 changes: 1 addition & 1 deletion discord/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -2288,7 +2288,7 @@ def upsert_guild_command(
self,
application_id: Snowflake,
guild_id: Snowflake,
payload: Dict[str, Any],
payload: command.ApplicationCommand,
) -> Response[command.ApplicationCommand]:
r = Route(
'POST',
Expand Down
Loading