text: # -*- coding: utf-8 -*-
  
  """
  The MIT License (MIT)
  
  Copyright (c) 2015-present Rapptz
  
  Permission is hereby granted, free of charge, to any person obtaining a
  copy of this software and associated documentation files (the "Software"),
  to deal in the Software without restriction, including without limitation
  the rights to use, copy, modify, merge, publish, distribute, sublicense,
  and/or sell copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following conditions:
  
  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.
  
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  DEALINGS IN THE SOFTWARE.
  """
  
  from __future__ import annotations
  from typing import Any, Dict, Generic, List, Optional, TYPE_CHECKING, Tuple, TypeVar, Union
  import asyncio
  
  from . import utils
  from .enums import try_enum, InteractionType, InteractionResponseType
  from .errors import InteractionResponded, HTTPException, ClientException
  from .flags import MessageFlags
  from .channel import PartialMessageable, ChannelType
  
  from .user import User
  from .member import Member
  from .message import Message, Attachment
  from .object import Object
  from .permissions import Permissions
  from .http import handle_message_parameters
  from .webhook.async_ import async_context, Webhook, interaction_response_params, interaction_message_response_params
  
  __all__ = (
      'Interaction',
      'InteractionMessage',
      'InteractionResponse',
  )
  
  if TYPE_CHECKING:
      from .types.interactions import (
          Interaction as InteractionPayload,
          InteractionData,
      )
      from .client import Client
      from .guild import Guild
      from .state import ConnectionState
      from .file import File
      from .mentions import AllowedMentions
      from aiohttp import ClientSession
      from .embeds import Embed
      from .ui.view import View
      from .app_commands.models import Choice, ChoiceT
      from .ui.modal import Modal
      from .channel import VoiceChannel, StageChannel, TextChannel, CategoryChannel, StoreChannel, PartialMessageable
      from .threads import Thread
  
      InteractionChannel = Union[
          VoiceChannel, StageChannel, TextChannel, CategoryChannel, StoreChannel, Thread, PartialMessageable
      ]
  
  MISSING: Any = utils.MISSING
  
  
  class Interaction:
      """Represents a Discord interaction.
  
      An interaction happens when a user does an action that needs to
      be notified. Current examples are slash commands and components.
  
      .. versionadded:: 2.0
  
      Attributes
      -----------
      id: :class:`int`
          The interaction's ID.
      type: :class:`InteractionType`
          The interaction type.
      guild_id: Optional[:class:`int`]
          The guild ID the interaction was sent from.
      channel_id: Optional[:class:`int`]
          The channel ID the interaction was sent from.
      application_id: :class:`int`
          The application ID that the interaction was for.
      user: Union[:class:`User`, :class:`Member`]
          The user or member that sent the interaction.
      message: Optional[:class:`Message`]
          The message that sent this interaction.
      token: :class:`str`
          The token to continue the interaction. These are valid
          for 15 minutes.
      data: :class:`dict`
          The raw interaction data.
      """
  
      __slots__: Tuple[str, ...] = (
          'id',
          'type',
          'guild_id',
          'channel_id',
          'data',
          'application_id',
          'message',
          'user',
          'token',
          'version',
          '_permissions',
          '_state',
          '_client',
          '_session',
          '_original_message',
          '_cs_response',
          '_cs_followup',
          '_cs_channel',
      )
  
      def __init__(self, *, data: InteractionPayload, state: ConnectionState):
          self._state: ConnectionState = state
          self._client: Client = state._get_client()
          self._session: ClientSession = state.http._HTTPClient__session  # type: ignore - Mangled attribute for __session
          self._original_message: Optional[InteractionMessage] = None
          self._from_data(data)
  
      def _from_data(self, data: InteractionPayload):
          self.id: int = int(data['id'])
          self.type: InteractionType = try_enum(InteractionType, data['type'])
          self.data: Optional[InteractionData] = data.get('data')
          self.token: str = data['token']
          self.version: int = data['version']
          self.channel_id: Optional[int] = utils._get_as_snowflake(data, 'channel_id')
          self.guild_id: Optional[int] = utils._get_as_snowflake(data, 'guild_id')
          self.application_id: int = int(data['application_id'])
  
          self.message: Optional[Message]
          try:
              # The channel and message payloads are mismatched yet handled properly at runtime
              self.message = Message(state=self._state, channel=self.channel, data=data['message'])  # type: ignore
          except KeyError:
              self.message = None
  
          self.user: Union[User, Member] = MISSING
          self._permissions: int = 0
  
          # TODO: there's a potential data loss here
          if self.guild_id:
              guild = self.guild or Object(id=self.guild_id)
              try:
                  member = data['member']  # type: ignore - The key is optional and handled
              except KeyError:
                  pass
              else:
                  # The fallback to Object for guild causes a type check error but is explicitly allowed here
                  self.user = Member(state=self._state, guild=guild, data=member)  # type: ignore
                  self._permissions = self.user._permissions or 0
          else:
              try:
                  self.user = User(state=self._state, data=data['user'])  # type: ignore - The key is optional and handled
              except KeyError:
                  pass
  
      @property
      def client(self) -> Client:
          """:class:`Client`: The client that is handling this interaction."""
          return self._client
  
      @property
      def guild(self) -> Optional[Guild]:
          """Optional[:class:`Guild`]: The guild the interaction was sent from."""
          return self._state and self._state._get_guild(self.guild_id)
  
      @utils.cached_slot_property('_cs_channel')
      def channel(self) -> Optional[InteractionChannel]:
          """Optional[Union[:class:`abc.GuildChannel`, :class:`PartialMessageable`, :class:`Thread`]]: The channel the interaction was sent from.
  
          Note that due to a Discord limitation, DM channels are not resolved since there is
          no data to complete them. These are :class:`PartialMessageable` instead.
          """
          guild = self.guild
          channel = guild and guild._resolve_channel(self.channel_id)
          if channel is None:
              if self.channel_id is not None:
                  type = ChannelType.text if self.guild_id is not None else ChannelType.private
                  return PartialMessageable(state=self._state, id=self.channel_id, type=type)
              return None
          return channel
  
      @property
      def permissions(self) -> Permissions:
          """:class:`Permissions`: The resolved permissions of the member in the channel, including overwrites.
  
          In a non-guild context where this doesn't apply, an empty permissions object is returned.
          """
          return Permissions(self._permissions)
  
      @utils.cached_slot_property('_cs_response')
      def response(self) -> InteractionResponse:
          """:class:`InteractionResponse`: Returns an object responsible for handling responding to the interaction.
  
          A response can only be done once. If secondary messages need to be sent, consider using :attr:`followup`
          instead.
          """
          return InteractionResponse(self)
  
      @utils.cached_slot_property('_cs_followup')
      def followup(self) -> Webhook:
          """:class:`Webhook`: Returns the follow up webhook for follow up interactions."""
          payload = {
              'id': self.application_id,
              'type': 3,
              'token': self.token,
          }
          return Webhook.from_state(data=payload, state=self._state)
  
      async def original_message(self) -> InteractionMessage:
          """|coro|
  
          Fetches the original interaction response message associated with the interaction.
  
          If the interaction response was :meth:`InteractionResponse.send_message` then this would
          return the message that was sent using that response. Otherwise, this would return
          the message that triggered the interaction.
  
          Repeated calls to this will return a cached value.
  
          Raises
          -------
          HTTPException
              Fetching the original response message failed.
          ClientException
              The channel for the message could not be resolved.
  
          Returns
          --------
          InteractionMessage
              The original interaction response message.
          """
  
          if self._original_message is not None:
              return self._original_message
  
          # TODO: fix later to not raise?
          channel = self.channel
          if channel is None:
              raise ClientException('Channel for message could not be resolved')
  
          adapter = async_context.get()
          data = await adapter.get_original_interaction_response(
              application_id=self.application_id,
              token=self.token,
              session=self._session,
          )
          state = _InteractionMessageState(self, self._state)
          # The state and channel parameters are mocked here
          message = InteractionMessage(state=state, channel=channel, data=data)  # type: ignore
          self._original_message = message
          return message
  
      async def edit_original_message(
          self,
          *,
          content: Optional[str] = MISSING,
          embeds: List[Embed] = MISSING,
          embed: Optional[Embed] = MISSING,
          attachments: List[Union[Attachment, File]] = MISSING,
          view: Optional[View] = MISSING,
          allowed_mentions: Optional[AllowedMentions] = None,
      ) -> InteractionMessage:
          """|coro|
  
          Edits the original interaction response message.
  
          This is a lower level interface to :meth:`InteractionMessage.edit` in case
          you do not want to fetch the message and save an HTTP request.
  
          This method is also the only way to edit the original message if
          the message sent was ephemeral.
  
          Parameters
          ------------
          content: Optional[:class:`str`]
              The content to edit the message with or ``None`` to clear it.
          embeds: List[:class:`Embed`]
              A list of embeds to edit the message with.
          embed: Optional[:class:`Embed`]
              The embed to edit the message with. ``None`` suppresses the embeds.
              This should not be mixed with the ``embeds`` parameter.
          attachments: List[Union[:class:`Attachment`, :class:`File`]]
              A list of attachments to keep in the message as well as new files to upload. If ``[]`` is passed
              then all attachments are removed.
  
              .. note::
  
                  New files will always appear after current attachments.
  
          allowed_mentions: :class:`AllowedMentions`
              Controls the mentions being processed in this message.
              See :meth:`.abc.Messageable.send` for more information.
          view: Optional[:class:`~discord.ui.View`]
              The updated view to update this message with. If ``None`` is passed then
              the view is removed.
  
          Raises
          -------
          HTTPException
              Editing the message failed.
          Forbidden
              Edited a message that is not yours.
          TypeError
              You specified both ``embed`` and ``embeds``
          ValueError
              The length of ``embeds`` was invalid.
  
          Returns
          --------
          :class:`InteractionMessage`
              The newly edited message.
          """
  
          previous_mentions: Optional[AllowedMentions] = self._state.allowed_mentions
          params = handle_message_parameters(
              content=content,
              attachments=attachments,
              embed=embed,
              embeds=embeds,
              view=view,
              allowed_mentions=allowed_mentions,
              previous_allowed_mentions=previous_mentions,
          )
          adapter = async_context.get()
          data = await adapter.edit_original_interaction_response(
              self.application_id,
              self.token,
              session=self._session,
              payload=params.payload,
              multipart=params.multipart,
              files=params.files,
          )
  
          # The message channel types should always match
          message = InteractionMessage(state=self._state, channel=self.channel, data=data)  # type: ignore
          if view and not view.is_finished():
              self._state.store_view(view, message.id)
          return message
  
      async def delete_original_message(self) -> None:
          """|coro|
  
          Deletes the original interaction response message.
  
          This is a lower level interface to :meth:`InteractionMessage.delete` in case
          you do not want to fetch the message and save an HTTP request.
  
          Raises
          -------
          HTTPException
              Deleting the message failed.
          Forbidden
              Deleted a message that is not yours.
          """
          adapter = async_context.get()
          await adapter.delete_original_interaction_response(
              self.application_id,
              self.token,
              session=self._session,
          )
  
  
  class InteractionResponse:
      """Represents a Discord interaction response.
  
      This type can be accessed through :attr:`Interaction.response`.
  
      .. versionadded:: 2.0
      """
  
      __slots__: Tuple[str, ...] = (
          '_responded',
          '_parent',
      )
  
      def __init__(self, parent: Interaction):
          self._parent: Interaction = parent
          self._responded: bool = False
  
      def is_done(self) -> bool:
          """:class:`bool`: Indicates whether an interaction response has been done before.
  
          An interaction can only be responded to once.
          """
          return self._responded
  
      async def defer(self, *, ephemeral: bool = False, thinking: bool = False) -> None:
          """|coro|
  
          Defers the interaction response.
  
          This is typically used when the interaction is acknowledged
          and a secondary action will be done later.
  
          This is only supported with the following interaction types:
  
          - :attr:`InteractionType.application_command`
          - :attr:`InteractionType.component`
          - :attr:`InteractionType.modal_submit`
  
          Parameters
          -----------
          ephemeral: :class:`bool`
              Indicates whether the deferred message will eventually be ephemeral.
              This only applies to :attr:`InteractionType.application_command` interactions, or if ``thinking`` is ``True``.
          thinking: :class:`bool`
              Indicates whether the deferred type should be :attr:`InteractionResponseType.deferred_channel_message`
              instead of the default :attr:`InteractionResponseType.deferred_message_update` if both are valid.
              In UI terms, this is represented as if the bot is thinking of a response. It is your responsibility to
              eventually send a followup message via :attr:`Interaction.followup` to make this thinking state go away.
              Application commands (AKA Slash commands) cannot use :attr:`InteractionResponseType.deferred_message_update`.
  
          Raises
          -------
          HTTPException
              Deferring the interaction failed.
          InteractionResponded
              This interaction has already been responded to before.
          """
          if self._responded:
              raise InteractionResponded(self._parent)
  
          defer_type: int = 0
          data: Optional[Dict[str, Any]] = None
          parent = self._parent
          if parent.type is InteractionType.component or parent.type is InteractionType.modal_submit:
              defer_type = (
                  InteractionResponseType.deferred_channel_message.value
                  if thinking
                  else InteractionResponseType.deferred_message_update.value
              )
              if thinking and ephemeral:
                  data = {'flags': 64}
          elif parent.type is InteractionType.application_command:
              defer_type = InteractionResponseType.deferred_channel_message.value
              if ephemeral:
                  data = {'flags': 64}
  
          if defer_type:
              adapter = async_context.get()
              params = interaction_response_params(type=defer_type, data=data)
              await adapter.create_interaction_response(parent.id, parent.token, session=parent._session, params=params)
              self._responded = True
  
      async def pong(self) -> None:
          """|coro|
  
          Pongs the ping interaction.
  
          This should rarely be used.
  
          Raises
          -------
          HTTPException
              Ponging the interaction failed.
          InteractionResponded
              This interaction has already been responded to before.
          """
          if self._responded:
              raise InteractionResponded(self._parent)
  
          parent = self._parent
          if parent.type is InteractionType.ping:
              adapter = async_context.get()
              params = interaction_response_params(InteractionResponseType.pong.value)
              await adapter.create_interaction_response(parent.id, parent.token, session=parent._session, params=params)
              self._responded = True
  
      async def send_message(
          self,
          content: Optional[Any] = None,
          *,
          embed: Embed = MISSING,
          embeds: List[Embed] = MISSING,
          file: File = MISSING,
          files: List[File] = MISSING,
          view: View = MISSING,
          tts: bool = False,
          ephemeral: bool = False,
          allowed_mentions: AllowedMentions = MISSING,
      ) -> None:
          """|coro|
  
          Responds to this interaction by sending a message.
  
          Parameters
          -----------
          content: Optional[:class:`str`]
              The content of the message to send.
          embeds: List[:class:`Embed`]
              A list of embeds to send with the content. Maximum of 10. This cannot
              be mixed with the ``embed`` parameter.
          embed: :class:`Embed`
              The rich embed for the content to send. This cannot be mixed with
              ``embeds`` parameter.
          file: :class:`~discord.File`
              The file to upload.
          files: List[:class:`~discord.File`]
              A list of files to upload. Must be a maximum of 10.
          tts: :class:`bool`
              Indicates if the message should be sent using text-to-speech.
          view: :class:`discord.ui.View`
              The view to send with the message.
          ephemeral: :class:`bool`
              Indicates if the message should only be visible to the user who started the interaction.
              If a view is sent with an ephemeral message and it has no timeout set then the timeout
              is set to 15 minutes.
          allowed_mentions: :class:`~discord.AllowedMentions`
              Controls the mentions being processed in this message. See :meth:`.abc.Messageable.send` for
              more information.
  
          Raises
          -------
          HTTPException
              Sending the message failed.
          TypeError
              You specified both ``embed`` and ``embeds`` or ``file`` and ``files``.
          ValueError
              The length of ``embeds`` was invalid.
          InteractionResponded
              This interaction has already been responded to before.
          """
          if self._responded:
              raise InteractionResponded(self._parent)
  
          if ephemeral:
              flags = MessageFlags._from_value(64)
          else:
              flags = MISSING
  
          parent = self._parent
          adapter = async_context.get()
          params = interaction_message_response_params(
              type=InteractionResponseType.channel_message.value,
              content=content,
              tts=tts,
              embeds=embeds,
              embed=embed,
              file=file,
              files=files,
              previous_allowed_mentions=parent._state.allowed_mentions,
              allowed_mentions=allowed_mentions,
              flags=flags,
              view=view,
          )
  
          await adapter.create_interaction_response(
              parent.id,
              parent.token,
              session=parent._session,
              params=params,
          )
  
          if view is not MISSING:
              if ephemeral and view.timeout is None:
                  view.timeout = 15 * 60.0
  
              self._parent._state.store_view(view)
  
          self._responded = True
  
      async def edit_message(
          self,
          *,
          content: Optional[Any] = MISSING,
          embed: Optional[Embed] = MISSING,
          embeds: List[Embed] = MISSING,
          attachments: List[Union[Attachment, File]] = MISSING,
          view: Optional[View] = MISSING,
          allowed_mentions: Optional[AllowedMentions] = MISSING,
      ) -> None:
          """|coro|
  
          Responds to this interaction by editing the original message of
          a component interaction.
  
          Parameters
          -----------
          content: Optional[:class:`str`]
              The new content to replace the message with. ``None`` removes the content.
          embeds: List[:class:`Embed`]
              A list of embeds to edit the message with.
          embed: Optional[:class:`Embed`]
              The embed to edit the message with. ``None`` suppresses the embeds.
              This should not be mixed with the ``embeds`` parameter.
          attachments: List[Union[:class:`Attachment`, :class:`File`]]
              A list of attachments to keep in the message as well as new files to upload. If ``[]`` is passed
              then all attachments are removed.
  
              .. note::
  
                  New files will always appear after current attachments.
  
          view: Optional[:class:`~discord.ui.View`]
              The updated view to update this message with. If ``None`` is passed then
              the view is removed.
          allowed_mentions: Optional[:class:`~discord.AllowedMentions`]
              Controls the mentions being processed in this message. See :meth:`.Message.edit`
              for more information.
  
          Raises
          -------
          HTTPException
              Editing the message failed.
          TypeError
              You specified both ``embed`` and ``embeds``.
          InteractionResponded
              This interaction has already been responded to before.
          """
          if self._responded:
              raise InteractionResponded(self._parent)
  
          parent = self._parent
          msg = parent.message
          state = parent._state
          message_id = msg.id if msg else None
          if parent.type is not InteractionType.component:
              return
  
          if view is not MISSING and message_id is not None:
              state.prevent_view_updates_for(message_id)
  
          adapter = async_context.get()
          params = interaction_message_response_params(
              type=InteractionResponseType.message_update.value,
              content=content,
              embed=embed,
              embeds=embeds,
              view=view,
              attachments=attachments,
              previous_allowed_mentions=parent._state.allowed_mentions,
              allowed_mentions=allowed_mentions,
          )
  
          await adapter.create_interaction_response(
              parent.id,
              parent.token,
              session=parent._session,
              params=params,
          )
  
          if view and not view.is_finished():
              state.store_view(view, message_id)
  
          self._responded = True
  
      async def send_modal(self, modal: Modal, /):
          """|coro|
  
          Responds to this interaction by sending a modal.
  
          Parameters
          -----------
          modal: :class:`~discord.ui.Modal`
              The modal to send.
  
          Raises
          -------
          HTTPException
              Sending the modal failed.
          InteractionResponded
              This interaction has already been responded to before.
          """
          if self._responded:
              raise InteractionResponded(self._parent)
  
          parent = self._parent
  
          adapter = async_context.get()
  
          params = interaction_response_params(InteractionResponseType.modal.value, modal.to_dict())
          await adapter.create_interaction_response(
              parent.id,
              parent.token,
              session=parent._session,
              params=params,
          )
  
          self._parent._state.store_view(modal)
          self._responded = True
  
      async def autocomplete(self, choices: List[Choice[ChoiceT]]) -> None:
          """|coro|
  
          Responds to this interaction by giving the user the choices they can use.
  
          Parameters
          -----------
          choices: List[:class:`~discord.app_commands.Choice`]
              The list of new choices as the user is typing.
  
          Raises
          -------
          HTTPException
              Sending the choices failed.
          ValueError
              This interaction cannot respond with autocomplete.
          InteractionResponded
              This interaction has already been responded to before.
          """
          if self._responded:
              raise InteractionResponded(self._parent)
  
          payload: Dict[str, Any] = {
              'choices': [option.to_dict() for option in choices],
          }
  
          parent = self._parent
          if parent.type is not InteractionType.autocomplete:
              raise ValueError('cannot respond to this interaction with autocomplete.')
  
          adapter = async_context.get()
          params = interaction_response_params(type=InteractionResponseType.autocomplete_result.value, data=payload)
          await adapter.create_interaction_response(
              parent.id,
              parent.token,
              session=parent._session,
              params=params,
          )
  
          self._responded = True
  
  
  class _InteractionMessageState:
      __slots__ = ('_parent', '_interaction')
  
      def __init__(self, interaction: Interaction, parent: ConnectionState):
          self._interaction: Interaction = interaction
          self._parent: ConnectionState = parent
  
      def _get_guild(self, guild_id):
          return self._parent._get_guild(guild_id)
  
      def store_user(self, data):
          return self._parent.store_user(data)
  
      def create_user(self, data):
          return self._parent.create_user(data)
  
      @property
      def http(self):
          return self._parent.http
  
      def __getattr__(self, attr):
          return getattr(self._parent, attr)
  
  
  class InteractionMessage(Message):
      """Represents the original interaction response message.
  
      This allows you to edit or delete the message associated with
      the interaction response. To retrieve this object see :meth:`Interaction.original_message`.
  
      This inherits from :class:`discord.Message` with changes to
      :meth:`edit` and :meth:`delete` to work.
  
      .. versionadded:: 2.0
      """
  
      __slots__ = ()
      _state: _InteractionMessageState
  
      async def edit(
          self,
          content: Optional[str] = MISSING,
          embeds: List[Embed] = MISSING,
          embed: Optional[Embed] = MISSING,
          attachments: List[Union[Attachment, File]] = MISSING,
          view: Optional[View] = MISSING,
          allowed_mentions: Optional[AllowedMentions] = None,
      ) -> InteractionMessage:
          """|coro|
  
          Edits the message.
  
          Parameters
          ------------
          content: Optional[:class:`str`]
              The content to edit the message with or ``None`` to clear it.
          embeds: List[:class:`Embed`]
              A list of embeds to edit the message with.
          embed: Optional[:class:`Embed`]
              The embed to edit the message with. ``None`` suppresses the embeds.
              This should not be mixed with the ``embeds`` parameter.
          attachments: List[Union[:class:`Attachment`, :class:`File`]]
              A list of attachments to keep in the message as well as new files to upload. If ``[]`` is passed
              then all attachments are removed.
  
              .. note::
  
                  New files will always appear after current attachments.
  
          allowed_mentions: :class:`AllowedMentions`
              Controls the mentions being processed in this message.
              See :meth:`.abc.Messageable.send` for more information.
          view: Optional[:class:`~discord.ui.View`]
              The updated view to update this message with. If ``None`` is passed then
              the view is removed.
  
          Raises
          -------
          HTTPException
              Editing the message failed.
          Forbidden
              Edited a message that is not yours.
          TypeError
              You specified both ``embed`` and ``embeds``
          ValueError
              The length of ``embeds`` was invalid.
  
          Returns
          ---------
          :class:`InteractionMessage`
              The newly edited message.
          """
          return await self._state._interaction.edit_original_message(
              content=content,
              embeds=embeds,
              embed=embed,
              attachments=attachments,
              view=view,
              allowed_mentions=allowed_mentions,
          )
  
      async def add_files(self, *files: File) -> InteractionMessage:
          r"""|coro|
  
          Adds new files to the end of the message attachments.
  
          .. versionadded:: 2.0
  
          Parameters
          -----------
          \*files: :class:`File`
              New files to add to the message.
  
          Raises
          -------
          HTTPException
              Editing the message failed.
          Forbidden
              Tried to edit a message that isn't yours.
  
          Returns
          ---------
          :class:`InteractionMessage`
              The newly edited message.
          """
          return await self.edit(attachments=[*self.attachments, *files])
  
      async def remove_attachments(self, *attachments: Attachment) -> InteractionMessage:
          r"""|coro|
  
          Removes attachments from the message.
  
          .. versionadded:: 2.0
  
          Parameters
          -----------
          \*attachments: :class:`Attachment`
              Attachments to remove from the message.
  
          Raises
          -------
          HTTPException
              Editing the message failed.
          Forbidden
              Tried to edit a message that isn't yours.
  
          Returns
          ---------
          :class:`InteractionMessage`
              The newly edited message.
          """
          return await self.edit(attachments=[a for a in self.attachments if a not in attachments])
  
      async def delete(self, *, delay: Optional[float] = None) -> None:
          """|coro|
  
          Deletes the message.
  
          Parameters
          -----------
          delay: Optional[:class:`float`]
              If provided, the number of seconds to wait before deleting the message.
              The waiting is done in the background and deletion failures are ignored.
  
          Raises
          ------
          Forbidden
              You do not have proper permissions to delete the message.
          NotFound
              The message was deleted already.
          HTTPException
              Deleting the message failed.
          """
  
          if delay is not None:
  
              async def inner_call(delay: float = delay):
                  await asyncio.sleep(delay)
                  try:
                      await self._state._interaction.delete_original_message()
                  except HTTPException:
                      pass
  
              asyncio.create_task(inner_call())
          else:
              await self._state._interaction.delete_original_message()
  