Skip to content

Context

attrs class Resolved

Represents resolved data in an interaction.

Attr attributes:

Name Type Description
channels Dict[Snowflake_Type, TYPE_MESSAGEABLE_CHANNEL]

A dictionary of channels mentioned in the interaction

members Dict[Snowflake_Type, Member]

A dictionary of members mentioned in the interaction

users Dict[Snowflake_Type, User]

A dictionary of users mentioned in the interaction

roles Dict[Snowflake_Type, Role]

A dictionary of roles mentioned in the interaction

messages Dict[Snowflake_Type, Message]

A dictionary of messages mentioned in the interaction

attachments Dict[Snowflake_Type, Attachment]

A dictionary of attachments tied to the interaction

Source code in naff/models/naff/context.py
@define()
class Resolved:
    """Represents resolved data in an interaction."""

    channels: Dict["Snowflake_Type", "TYPE_MESSAGEABLE_CHANNEL"] = field(
        factory=dict, metadata=docs("A dictionary of channels mentioned in the interaction")
    )
    members: Dict["Snowflake_Type", "Member"] = field(
        factory=dict, metadata=docs("A dictionary of members mentioned in the interaction")
    )
    users: Dict["Snowflake_Type", "User"] = field(
        factory=dict, metadata=docs("A dictionary of users mentioned in the interaction")
    )
    roles: Dict["Snowflake_Type", "Role"] = field(
        factory=dict, metadata=docs("A dictionary of roles mentioned in the interaction")
    )
    messages: Dict["Snowflake_Type", "Message"] = field(
        factory=dict, metadata=docs("A dictionary of messages mentioned in the interaction")
    )
    attachments: Dict["Snowflake_Type", "Attachment"] = field(
        factory=dict, metadata=docs("A dictionary of attachments tied to the interaction")
    )

    @classmethod
    def from_dict(cls, client: "Client", data: dict, guild_id: Optional["Snowflake_Type"] = None) -> "Resolved":
        new_cls = cls()

        if channels := data.get("channels"):
            for key, _channel in channels.items():
                new_cls.channels[key] = client.cache.place_channel_data(_channel)

        if members := data.get("members"):
            for key, _member in members.items():
                new_cls.members[key] = client.cache.place_member_data(
                    guild_id, {**_member, "user": {**data["users"][key]}}
                )

        if users := data.get("users"):
            for key, _user in users.items():
                new_cls.users[key] = client.cache.place_user_data(_user)

        if roles := data.get("roles"):
            for key, _role in roles.items():
                new_cls.roles[key] = client.cache.get_role(to_snowflake(key))

        if messages := data.get("messages"):
            for key, _msg in messages.items():
                new_cls.messages[key] = client.cache.place_message_data(_msg)

        if attachments := data.get("attachments"):
            for key, _attach in attachments.items():
                new_cls.attachments[key] = Attachment.from_dict(_attach, client)

        return new_cls

attrs class Context

Represents the context of a command.

Attr attributes:

Name Type Description
invoke_target str

The name of the command to be invoked

command Optional[BaseCommand]

The command to be invoked

args List

The list of arguments to be passed to the command

kwargs Dict

The list of keyword arguments to be passed

author Union[Member, User]

The author of the message

channel TYPE_MESSAGEABLE_CHANNEL

The channel this was sent within

guild_id Snowflake_Type

The guild this was sent within, if not a DM

message Message

The message associated with this context

Source code in naff/models/naff/context.py
@define
class Context:
    """Represents the context of a command."""

    _client: "Client" = field(default=None)
    invoke_target: str = field(default=None, metadata=docs("The name of the command to be invoked"))
    command: Optional["BaseCommand"] = field(default=None, metadata=docs("The command to be invoked"))

    args: List = field(factory=list, metadata=docs("The list of arguments to be passed to the command"))
    kwargs: Dict = field(factory=dict, metadata=docs("The list of keyword arguments to be passed"))

    author: Union["Member", "User"] = field(default=None, metadata=docs("The author of the message"))
    channel: "TYPE_MESSAGEABLE_CHANNEL" = field(default=None, metadata=docs("The channel this was sent within"))
    guild_id: "Snowflake_Type" = field(
        default=None, converter=to_optional_snowflake, metadata=docs("The guild this was sent within, if not a DM")
    )
    message: "Message" = field(default=None, metadata=docs("The message associated with this context"))

    @property
    def guild(self) -> Optional["Guild"]:
        return self._client.cache.get_guild(self.guild_id)

    @property
    def bot(self) -> "Client":
        """A reference to the bot instance."""
        return self._client

    @property
    def voice_state(self) -> Optional["ActiveVoiceState"]:
        return self._client.cache.get_bot_voice_state(self.guild_id)

property readonly bot: Client

A reference to the bot instance.

attrs class InteractionContext (_BaseInteractionContext, SendMixin)

Represents the context of an interaction.

Ephemeral messages:

Ephemeral messages allow you to send messages that only the author of the interaction can see. They are best considered as fire-and-forget, in the sense that you cannot edit them once they have been sent.

Should you attach a component (ie. button) to the ephemeral message, you will be able to edit it when responding to a button interaction.

Attr attributes:

Name Type Description
invoke_target str

The name of the command to be invoked

command Optional[BaseCommand]

The command to be invoked

args List

The list of arguments to be passed to the command

kwargs Dict

The list of keyword arguments to be passed

author Union[Member, User]

The author of the message

channel TYPE_MESSAGEABLE_CHANNEL

The channel this was sent within

guild_id Snowflake_Type

The guild this was sent within, if not a DM

message Message

The message associated with this context

interaction_id str

The id of the interaction

target_id Snowflake_Type

The ID of the target, used for context menus to show what was clicked on

app_permissions Permissions

The permissions this interaction has

locale str

The selected language of the invoking user (https://discord.com/developers/docs/reference#locales)

guild_locale str

The guild's preferred locale

deferred bool

Is this interaction deferred?

responded bool

Have we responded to the interaction?

ephemeral bool

Are responses to this interaction hidden

resolved Resolved

Discord objects mentioned within this interaction

data Dict

The raw data of this interaction

Source code in naff/models/naff/context.py
@define
class InteractionContext(_BaseInteractionContext, SendMixin):
    """
    Represents the context of an interaction.

    !!! info "Ephemeral messages:"
        Ephemeral messages allow you to send messages that only the author of the interaction can see.
        They are best considered as `fire-and-forget`, in the sense that you cannot edit them once they have been sent.

        Should you attach a component (ie. button) to the ephemeral message,
        you will be able to edit it when responding to a button interaction.

    """

    async def defer(self, ephemeral: bool = False) -> None:
        """
        Defers the response, showing a loading state.

        Args:
            ephemeral: Should the response be ephemeral

        """
        if self.deferred or self.responded:
            raise AlreadyDeferred("You have already responded to this interaction!")

        payload = {"type": CallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE}
        if ephemeral:
            payload["data"] = {"flags": MessageFlags.EPHEMERAL}

        await self._client.http.post_initial_response(payload, self.interaction_id, self._token)
        self.ephemeral = ephemeral
        self.deferred = True

    async def _send_http_request(
        self, message_payload: Union[dict, "FormData"], files: list["UPLOADABLE_TYPE"] | None = None
    ) -> dict:
        if self.responded:
            message_data = await self._client.http.post_followup(
                message_payload, self._client.app.id, self._token, files=files
            )
        else:
            if isinstance(message_payload, FormData) and not self.deferred:
                await self.defer(self.ephemeral)
            if self.deferred:
                message_data = await self._client.http.edit_interaction_message(
                    message_payload, self._client.app.id, self._token, files=files
                )
                self.deferred = False
            else:
                payload = {"type": CallbackTypes.CHANNEL_MESSAGE_WITH_SOURCE, "data": message_payload}
                await self._client.http.post_initial_response(payload, self.interaction_id, self._token, files=files)
                message_data = await self._client.http.get_interaction_message(self._client.app.id, self._token)
            self.responded = True

        return message_data

    async def send(
        self,
        content: Optional[str] = None,
        embeds: Optional[Union[List[Union["Embed", dict]], Union["Embed", dict]]] = None,
        embed: Optional[Union["Embed", dict]] = None,
        components: Optional[
            Union[List[List[Union["BaseComponent", dict]]], List[Union["BaseComponent", dict]], "BaseComponent", dict]
        ] = None,
        stickers: Optional[Union[List[Union["Sticker", "Snowflake_Type"]], "Sticker", "Snowflake_Type"]] = None,
        allowed_mentions: Optional[Union["AllowedMentions", dict]] = None,
        reply_to: Optional[Union["MessageReference", "Message", dict, "Snowflake_Type"]] = None,
        files: Optional[Union[UPLOADABLE_TYPE, List[UPLOADABLE_TYPE]]] = None,
        file: Optional[UPLOADABLE_TYPE] = None,
        tts: bool = False,
        suppress_embeds: bool = False,
        flags: Optional[Union[int, "MessageFlags"]] = None,
        ephemeral: bool = False,
    ) -> "Message":
        """
        Send a message.

        Args:
            content: Message text content.
            embeds: Embedded rich content (up to 6000 characters).
            embed: Embedded rich content (up to 6000 characters).
            components: The components to include with the message.
            stickers: IDs of up to 3 stickers in the server to send in the message.
            allowed_mentions: Allowed mentions for the message.
            reply_to: Message to reference, must be from the same channel.
            files: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
            file: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
            tts: Should this message use Text To Speech.
            suppress_embeds: Should embeds be suppressed on this send
            flags: Message flags to apply.
            ephemeral bool: Should this message be sent as ephemeral (hidden)

        Returns:
            New message object that was sent.

        """
        if ephemeral:
            flags = MessageFlags.EPHEMERAL
            self.ephemeral = True

        if suppress_embeds:
            if isinstance(flags, int):
                flags = MessageFlags(flags)
            flags = flags | MessageFlags.SUPPRESS_EMBEDS

        return await super().send(
            content,
            embeds=embeds,
            embed=embed,
            components=components,
            stickers=stickers,
            allowed_mentions=allowed_mentions,
            reply_to=reply_to,
            files=files,
            file=file,
            tts=tts,
            flags=flags,
        )

    @property
    def target(self) -> "Absent[Member | User | Message]":
        """For context menus, this will be the object of which was clicked on."""
        thing = MISSING

        match self._context_type:
            # Only searches caches based on what kind of context menu this is

            case CommandTypes.USER:
                # This can only be in the member or user cache
                caches = (
                    (self._client.cache.get_member, (self.guild_id, self.target_id)),
                    (self._client.cache.get_user, self.target_id),
                )
            case CommandTypes.MESSAGE:
                # This can only be in the message cache
                caches = ((self._client.cache.get_message, (self.channel.id, self.target_id)),)
            case _:
                # Most likely a new context type, check all rational caches for the target_id
                logger.warning(f"New Context Type Detected. Please Report: {self._context_type}")
                caches = (
                    (self._client.cache.get_message, (self.channel.id, self.target_id)),
                    (self._client.cache.get_member, (self.guild_id, self.target_id)),
                    (self._client.cache.get_user, self.target_id),
                    (self._client.cache.get_channel, self.target_id),
                    (self._client.cache.get_role, self.target_id),
                    (self._client.cache.get_emoji, self.target_id),  # unlikely, so check last
                )

        for cache, keys in caches:
            thing = cache(*keys)
            if thing is not None:
                break
        return thing

inherited property readonly bot: Client

A reference to the bot instance.

inherited property readonly expires_at: Timestamp

The timestamp the interaction is expected to expire at.

inherited property readonly expired: bool

Has the interaction expired yet?

async inherited method send_modal(self, modal)

Respond using a modal.

Parameters:

Name Type Description Default
modal Union[dict, Modal]

The modal to respond with

required

Returns:

Type Description
Union[dict, Modal]

The modal used.

Source code in naff/models/naff/context.py
async def send_modal(self, modal: Union[dict, "Modal"]) -> Union[dict, "Modal"]:
    """
    Respond using a modal.

    Args:
        modal: The modal to respond with

    Returns:
        The modal used.

    """
    payload = modal.to_dict() if not isinstance(modal, dict) else modal

    await self._client.http.post_initial_response(payload, self.interaction_id, self._token)

    self.responded = True
    return modal

async method defer(self, ephemeral)

Defers the response, showing a loading state.

Parameters:

Name Type Description Default
ephemeral bool

Should the response be ephemeral

False
Source code in naff/models/naff/context.py
async def defer(self, ephemeral: bool = False) -> None:
    """
    Defers the response, showing a loading state.

    Args:
        ephemeral: Should the response be ephemeral

    """
    if self.deferred or self.responded:
        raise AlreadyDeferred("You have already responded to this interaction!")

    payload = {"type": CallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE}
    if ephemeral:
        payload["data"] = {"flags": MessageFlags.EPHEMERAL}

    await self._client.http.post_initial_response(payload, self.interaction_id, self._token)
    self.ephemeral = ephemeral
    self.deferred = True

async method send(self, content, embeds, embed, components, stickers, allowed_mentions, reply_to, files, file, tts, suppress_embeds, flags, ephemeral)

Send a message.

Parameters:

Name Type Description Default
content Optional[str]

Message text content.

None
embeds Union[List[Union[Embed, dict]], Embed, dict]

Embedded rich content (up to 6000 characters).

None
embed Union[Embed, dict]

Embedded rich content (up to 6000 characters).

None
components Union[List[List[Union[BaseComponent, dict]]], List[Union[BaseComponent, dict]], BaseComponent, dict]

The components to include with the message.

None
stickers Union[List[Union[Sticker, Snowflake_Type]], Sticker, Snowflake_Type]

IDs of up to 3 stickers in the server to send in the message.

None
allowed_mentions Union[AllowedMentions, dict]

Allowed mentions for the message.

None
reply_to Union[MessageReference, Message, dict, Snowflake_Type]

Message to reference, must be from the same channel.

None
files Union[naff.models.discord.file.File, io.IOBase, BinaryIO, pathlib.Path, str, List[Union[naff.models.discord.file.File, io.IOBase, BinaryIO, pathlib.Path, str]]]

Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.

None
file Union[naff.models.discord.file.File, io.IOBase, BinaryIO, pathlib.Path, str]

Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.

None
tts bool

Should this message use Text To Speech.

False
suppress_embeds bool

Should embeds be suppressed on this send

False
flags Union[int, MessageFlags]

Message flags to apply.

None
ephemeral bool

Should this message be sent as ephemeral (hidden)

False

Returns:

Type Description
Message

New message object that was sent.

Source code in naff/models/naff/context.py
async def send(
    self,
    content: Optional[str] = None,
    embeds: Optional[Union[List[Union["Embed", dict]], Union["Embed", dict]]] = None,
    embed: Optional[Union["Embed", dict]] = None,
    components: Optional[
        Union[List[List[Union["BaseComponent", dict]]], List[Union["BaseComponent", dict]], "BaseComponent", dict]
    ] = None,
    stickers: Optional[Union[List[Union["Sticker", "Snowflake_Type"]], "Sticker", "Snowflake_Type"]] = None,
    allowed_mentions: Optional[Union["AllowedMentions", dict]] = None,
    reply_to: Optional[Union["MessageReference", "Message", dict, "Snowflake_Type"]] = None,
    files: Optional[Union[UPLOADABLE_TYPE, List[UPLOADABLE_TYPE]]] = None,
    file: Optional[UPLOADABLE_TYPE] = None,
    tts: bool = False,
    suppress_embeds: bool = False,
    flags: Optional[Union[int, "MessageFlags"]] = None,
    ephemeral: bool = False,
) -> "Message":
    """
    Send a message.

    Args:
        content: Message text content.
        embeds: Embedded rich content (up to 6000 characters).
        embed: Embedded rich content (up to 6000 characters).
        components: The components to include with the message.
        stickers: IDs of up to 3 stickers in the server to send in the message.
        allowed_mentions: Allowed mentions for the message.
        reply_to: Message to reference, must be from the same channel.
        files: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
        file: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
        tts: Should this message use Text To Speech.
        suppress_embeds: Should embeds be suppressed on this send
        flags: Message flags to apply.
        ephemeral bool: Should this message be sent as ephemeral (hidden)

    Returns:
        New message object that was sent.

    """
    if ephemeral:
        flags = MessageFlags.EPHEMERAL
        self.ephemeral = True

    if suppress_embeds:
        if isinstance(flags, int):
            flags = MessageFlags(flags)
        flags = flags | MessageFlags.SUPPRESS_EMBEDS

    return await super().send(
        content,
        embeds=embeds,
        embed=embed,
        components=components,
        stickers=stickers,
        allowed_mentions=allowed_mentions,
        reply_to=reply_to,
        files=files,
        file=file,
        tts=tts,
        flags=flags,
    )

property readonly target: Absent[Member | User | Message]

For context menus, this will be the object of which was clicked on.

attrs class ComponentContext (InteractionContext)

Attr attributes:

Name Type Description
invoke_target str

The name of the command to be invoked

command Optional[BaseCommand]

The command to be invoked

args List

The list of arguments to be passed to the command

kwargs Dict

The list of keyword arguments to be passed

author Union[Member, User]

The author of the message

channel TYPE_MESSAGEABLE_CHANNEL

The channel this was sent within

guild_id Snowflake_Type

The guild this was sent within, if not a DM

message Message

The message associated with this context

interaction_id str

The id of the interaction

target_id Snowflake_Type

The ID of the target, used for context menus to show what was clicked on

app_permissions Permissions

The permissions this interaction has

locale str

The selected language of the invoking user (https://discord.com/developers/docs/reference#locales)

guild_locale str

The guild's preferred locale

deferred bool

Is this interaction deferred?

responded bool

Have we responded to the interaction?

ephemeral bool

Are responses to this interaction hidden

resolved Resolved

Discord objects mentioned within this interaction

data Dict

The raw data of this interaction

custom_id str

The ID given to the component that has been pressed

component_type int

The type of component that has been pressed

values List

The values set

defer_edit_origin bool

Are we editing the message the component is on

Source code in naff/models/naff/context.py
@define
class ComponentContext(InteractionContext):
    custom_id: str = field(default="", metadata=docs("The ID given to the component that has been pressed"))
    component_type: int = field(default=0, metadata=docs("The type of component that has been pressed"))

    values: List = field(factory=list, metadata=docs("The values set"))

    defer_edit_origin: bool = field(default=False, metadata=docs("Are we editing the message the component is on"))

    @classmethod
    def from_dict(cls, data: Dict, client: "Client") -> "ComponentContext":
        """Create a context object from a dictionary."""
        new_cls = super().from_dict(data, client)
        new_cls.token = data["token"]
        new_cls.interaction_id = data["id"]
        new_cls.custom_id = data["data"]["custom_id"]
        new_cls.component_type = data["data"]["component_type"]
        new_cls.message = client.cache.place_message_data(data["message"])
        new_cls.values = data["data"].get("values", [])

        return new_cls

    async def defer(self, ephemeral: bool = False, edit_origin: bool = False) -> None:
        """
        Defers the response, showing a loading state.

        Args:
            ephemeral: Should the response be ephemeral
            edit_origin: Whether we intend to edit the original message

        """
        if self.deferred or self.responded:
            raise AlreadyDeferred("You have already responded to this interaction!")

        payload = {
            "type": CallbackTypes.DEFERRED_UPDATE_MESSAGE
            if edit_origin
            else CallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE
        }

        if ephemeral:
            if edit_origin:
                raise ValueError("`edit_origin` and `ephemeral` are mutually exclusive")
            payload["data"] = {"flags": MessageFlags.EPHEMERAL}

        await self._client.http.post_initial_response(payload, self.interaction_id, self._token)
        self.deferred = True
        self.ephemeral = ephemeral
        self.defer_edit_origin = edit_origin

    async def edit_origin(
        self,
        content: str = None,
        embeds: Optional[Union[List[Union["Embed", dict]], Union["Embed", dict]]] = None,
        embed: Optional[Union["Embed", dict]] = None,
        components: Optional[
            Union[List[List[Union["BaseComponent", dict]]], List[Union["BaseComponent", dict]], "BaseComponent", dict]
        ] = None,
        allowed_mentions: Optional[Union["AllowedMentions", dict]] = None,
        files: Optional[Union[UPLOADABLE_TYPE, List[UPLOADABLE_TYPE]]] = None,
        file: Optional[UPLOADABLE_TYPE] = None,
        tts: bool = False,
    ) -> "Message":
        """
        Edits the original message of the component.

        Args:
            content: Message text content.
            embeds: Embedded rich content (up to 6000 characters).
            embed: Embedded rich content (up to 6000 characters).
            components: The components to include with the message.
            allowed_mentions: Allowed mentions for the message.
            reply_to: Message to reference, must be from the same channel.
            files: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
            file: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
            tts: Should this message use Text To Speech.

        Returns:
            The message after it was edited.

        """
        if not self.responded and not self.deferred and (files or file):
            # Discord doesn't allow files at initial response, so we defer then edit.
            await self.defer(edit_origin=True)

        message_payload = message.process_message_payload(
            content=content,
            embeds=embeds or embed,
            components=components,
            allowed_mentions=allowed_mentions,
            tts=tts,
        )

        message_data = None
        if self.deferred:
            if not self.defer_edit_origin:
                logger.warning(
                    "If you want to edit the original message, and need to defer, you must set the `edit_origin` kwarg to True!"
                )

            message_data = await self._client.http.edit_interaction_message(
                message_payload, self._client.app.id, self._token
            )
            self.deferred = False
            self.defer_edit_origin = False
        else:
            payload = {"type": CallbackTypes.UPDATE_MESSAGE, "data": message_payload}
            await self._client.http.post_initial_response(
                payload, self.interaction_id, self._token, files=files or file
            )
            message_data = await self._client.http.get_interaction_message(self._client.app.id, self._token)

        if message_data:
            self.message = self._client.cache.place_message_data(message_data)
            return self.message

inherited property readonly bot: Client

A reference to the bot instance.

inherited property readonly expires_at: Timestamp

The timestamp the interaction is expected to expire at.

inherited property readonly expired: bool

Has the interaction expired yet?

async inherited method send_modal(self, modal)

Respond using a modal.

Parameters:

Name Type Description Default
modal Union[dict, Modal]

The modal to respond with

required

Returns:

Type Description
Union[dict, Modal]

The modal used.

Source code in naff/models/naff/context.py
async def send_modal(self, modal: Union[dict, "Modal"]) -> Union[dict, "Modal"]:
    """
    Respond using a modal.

    Args:
        modal: The modal to respond with

    Returns:
        The modal used.

    """
    payload = modal.to_dict() if not isinstance(modal, dict) else modal

    await self._client.http.post_initial_response(payload, self.interaction_id, self._token)

    self.responded = True
    return modal

async inherited method send(self, content, embeds, embed, components, stickers, allowed_mentions, reply_to, files, file, tts, suppress_embeds, flags, ephemeral)

Send a message.

Parameters:

Name Type Description Default
content Optional[str]

Message text content.

None
embeds Union[List[Union[Embed, dict]], Embed, dict]

Embedded rich content (up to 6000 characters).

None
embed Union[Embed, dict]

Embedded rich content (up to 6000 characters).

None
components Union[List[List[Union[BaseComponent, dict]]], List[Union[BaseComponent, dict]], BaseComponent, dict]

The components to include with the message.

None
stickers Union[List[Union[Sticker, Snowflake_Type]], Sticker, Snowflake_Type]

IDs of up to 3 stickers in the server to send in the message.

None
allowed_mentions Union[AllowedMentions, dict]

Allowed mentions for the message.

None
reply_to Union[MessageReference, Message, dict, Snowflake_Type]

Message to reference, must be from the same channel.

None
files Union[naff.models.discord.file.File, io.IOBase, BinaryIO, pathlib.Path, str, List[Union[naff.models.discord.file.File, io.IOBase, BinaryIO, pathlib.Path, str]]]

Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.

None
file Union[naff.models.discord.file.File, io.IOBase, BinaryIO, pathlib.Path, str]

Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.

None
tts bool

Should this message use Text To Speech.

False
suppress_embeds bool

Should embeds be suppressed on this send

False
flags Union[int, MessageFlags]

Message flags to apply.

None
ephemeral bool

Should this message be sent as ephemeral (hidden)

False

Returns:

Type Description
Message

New message object that was sent.

Source code in naff/models/naff/context.py
async def send(
    self,
    content: Optional[str] = None,
    embeds: Optional[Union[List[Union["Embed", dict]], Union["Embed", dict]]] = None,
    embed: Optional[Union["Embed", dict]] = None,
    components: Optional[
        Union[List[List[Union["BaseComponent", dict]]], List[Union["BaseComponent", dict]], "BaseComponent", dict]
    ] = None,
    stickers: Optional[Union[List[Union["Sticker", "Snowflake_Type"]], "Sticker", "Snowflake_Type"]] = None,
    allowed_mentions: Optional[Union["AllowedMentions", dict]] = None,
    reply_to: Optional[Union["MessageReference", "Message", dict, "Snowflake_Type"]] = None,
    files: Optional[Union[UPLOADABLE_TYPE, List[UPLOADABLE_TYPE]]] = None,
    file: Optional[UPLOADABLE_TYPE] = None,
    tts: bool = False,
    suppress_embeds: bool = False,
    flags: Optional[Union[int, "MessageFlags"]] = None,
    ephemeral: bool = False,
) -> "Message":
    """
    Send a message.

    Args:
        content: Message text content.
        embeds: Embedded rich content (up to 6000 characters).
        embed: Embedded rich content (up to 6000 characters).
        components: The components to include with the message.
        stickers: IDs of up to 3 stickers in the server to send in the message.
        allowed_mentions: Allowed mentions for the message.
        reply_to: Message to reference, must be from the same channel.
        files: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
        file: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
        tts: Should this message use Text To Speech.
        suppress_embeds: Should embeds be suppressed on this send
        flags: Message flags to apply.
        ephemeral bool: Should this message be sent as ephemeral (hidden)

    Returns:
        New message object that was sent.

    """
    if ephemeral:
        flags = MessageFlags.EPHEMERAL
        self.ephemeral = True

    if suppress_embeds:
        if isinstance(flags, int):
            flags = MessageFlags(flags)
        flags = flags | MessageFlags.SUPPRESS_EMBEDS

    return await super().send(
        content,
        embeds=embeds,
        embed=embed,
        components=components,
        stickers=stickers,
        allowed_mentions=allowed_mentions,
        reply_to=reply_to,
        files=files,
        file=file,
        tts=tts,
        flags=flags,
    )

inherited property readonly target: Absent[Member | User | Message]

For context menus, this will be the object of which was clicked on.

classmethod method from_dict(data, client)

Create a context object from a dictionary.

Source code in naff/models/naff/context.py
@classmethod
def from_dict(cls, data: Dict, client: "Client") -> "ComponentContext":
    """Create a context object from a dictionary."""
    new_cls = super().from_dict(data, client)
    new_cls.token = data["token"]
    new_cls.interaction_id = data["id"]
    new_cls.custom_id = data["data"]["custom_id"]
    new_cls.component_type = data["data"]["component_type"]
    new_cls.message = client.cache.place_message_data(data["message"])
    new_cls.values = data["data"].get("values", [])

    return new_cls

async method defer(self, ephemeral, edit_origin)

Defers the response, showing a loading state.

Parameters:

Name Type Description Default
ephemeral bool

Should the response be ephemeral

False
edit_origin bool

Whether we intend to edit the original message

False
Source code in naff/models/naff/context.py
async def defer(self, ephemeral: bool = False, edit_origin: bool = False) -> None:
    """
    Defers the response, showing a loading state.

    Args:
        ephemeral: Should the response be ephemeral
        edit_origin: Whether we intend to edit the original message

    """
    if self.deferred or self.responded:
        raise AlreadyDeferred("You have already responded to this interaction!")

    payload = {
        "type": CallbackTypes.DEFERRED_UPDATE_MESSAGE
        if edit_origin
        else CallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE
    }

    if ephemeral:
        if edit_origin:
            raise ValueError("`edit_origin` and `ephemeral` are mutually exclusive")
        payload["data"] = {"flags": MessageFlags.EPHEMERAL}

    await self._client.http.post_initial_response(payload, self.interaction_id, self._token)
    self.deferred = True
    self.ephemeral = ephemeral
    self.defer_edit_origin = edit_origin

async method edit_origin(self, content, embeds, embed, components, allowed_mentions, files, file, tts)

Edits the original message of the component.

Parameters:

Name Type Description Default
content str

Message text content.

None
embeds Union[List[Union[Embed, dict]], Embed, dict]

Embedded rich content (up to 6000 characters).

None
embed Union[Embed, dict]

Embedded rich content (up to 6000 characters).

None
components Union[List[List[Union[BaseComponent, dict]]], List[Union[BaseComponent, dict]], BaseComponent, dict]

The components to include with the message.

None
allowed_mentions Union[AllowedMentions, dict]

Allowed mentions for the message.

None
reply_to

Message to reference, must be from the same channel.

required
files Union[naff.models.discord.file.File, io.IOBase, BinaryIO, pathlib.Path, str, List[Union[naff.models.discord.file.File, io.IOBase, BinaryIO, pathlib.Path, str]]]

Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.

None
file Union[naff.models.discord.file.File, io.IOBase, BinaryIO, pathlib.Path, str]

Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.

None
tts bool

Should this message use Text To Speech.

False

Returns:

Type Description
Message

The message after it was edited.

Source code in naff/models/naff/context.py
async def edit_origin(
    self,
    content: str = None,
    embeds: Optional[Union[List[Union["Embed", dict]], Union["Embed", dict]]] = None,
    embed: Optional[Union["Embed", dict]] = None,
    components: Optional[
        Union[List[List[Union["BaseComponent", dict]]], List[Union["BaseComponent", dict]], "BaseComponent", dict]
    ] = None,
    allowed_mentions: Optional[Union["AllowedMentions", dict]] = None,
    files: Optional[Union[UPLOADABLE_TYPE, List[UPLOADABLE_TYPE]]] = None,
    file: Optional[UPLOADABLE_TYPE] = None,
    tts: bool = False,
) -> "Message":
    """
    Edits the original message of the component.

    Args:
        content: Message text content.
        embeds: Embedded rich content (up to 6000 characters).
        embed: Embedded rich content (up to 6000 characters).
        components: The components to include with the message.
        allowed_mentions: Allowed mentions for the message.
        reply_to: Message to reference, must be from the same channel.
        files: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
        file: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
        tts: Should this message use Text To Speech.

    Returns:
        The message after it was edited.

    """
    if not self.responded and not self.deferred and (files or file):
        # Discord doesn't allow files at initial response, so we defer then edit.
        await self.defer(edit_origin=True)

    message_payload = message.process_message_payload(
        content=content,
        embeds=embeds or embed,
        components=components,
        allowed_mentions=allowed_mentions,
        tts=tts,
    )

    message_data = None
    if self.deferred:
        if not self.defer_edit_origin:
            logger.warning(
                "If you want to edit the original message, and need to defer, you must set the `edit_origin` kwarg to True!"
            )

        message_data = await self._client.http.edit_interaction_message(
            message_payload, self._client.app.id, self._token
        )
        self.deferred = False
        self.defer_edit_origin = False
    else:
        payload = {"type": CallbackTypes.UPDATE_MESSAGE, "data": message_payload}
        await self._client.http.post_initial_response(
            payload, self.interaction_id, self._token, files=files or file
        )
        message_data = await self._client.http.get_interaction_message(self._client.app.id, self._token)

    if message_data:
        self.message = self._client.cache.place_message_data(message_data)
        return self.message

attrs class AutocompleteContext (_BaseInteractionContext)

Attr attributes:

Name Type Description
invoke_target str

The name of the command to be invoked

command Optional[BaseCommand]

The command to be invoked

args List

The list of arguments to be passed to the command

kwargs Dict

The list of keyword arguments to be passed

author Union[Member, User]

The author of the message

channel TYPE_MESSAGEABLE_CHANNEL

The channel this was sent within

guild_id Snowflake_Type

The guild this was sent within, if not a DM

message Message

The message associated with this context

interaction_id str

The id of the interaction

target_id Snowflake_Type

The ID of the target, used for context menus to show what was clicked on

app_permissions Permissions

The permissions this interaction has

locale str

The selected language of the invoking user (https://discord.com/developers/docs/reference#locales)

guild_locale str

The guild's preferred locale

deferred bool

Is this interaction deferred?

responded bool

Have we responded to the interaction?

ephemeral bool

Are responses to this interaction hidden

resolved Resolved

Discord objects mentioned within this interaction

data Dict

The raw data of this interaction

focussed_option str

The option the user is currently filling in

Source code in naff/models/naff/context.py
@define
class AutocompleteContext(_BaseInteractionContext):
    focussed_option: str = field(default=MISSING, metadata=docs("The option the user is currently filling in"))

    @classmethod
    def from_dict(cls, data: Dict, client: "Client") -> "ComponentContext":
        """Create a context object from a dictionary."""
        new_cls = super().from_dict(data, client)

        return new_cls

    @property
    def input_text(self) -> str:
        """The text the user has entered so far."""
        return self.kwargs.get(self.focussed_option, "")

    async def send(self, choices: List[Union[str, int, float, Dict[str, Union[str, int, float]]]]) -> None:
        """
        Send your autocomplete choices to discord. Choices must be either a list of strings, or a dictionary following the following format:

        ```json
            {
              "name": str,
              "value": str
            }
        ```
        Where name is the text visible in Discord, and value is the data sent back to your client when that choice is
        chosen.

        Args:
            choices: 25 choices the user can pick

        """
        processed_choices = []
        for choice in choices:
            if isinstance(choice, (int, float)):
                processed_choices.append({"name": str(choice), "value": choice})
            elif isinstance(choice, dict):
                processed_choices.append(choice)
            else:
                choice = str(choice)
                processed_choices.append({"name": choice, "value": choice.replace(" ", "_")})

        payload = {"type": CallbackTypes.AUTOCOMPLETE_RESULT, "data": {"choices": processed_choices}}
        await self._client.http.post_initial_response(payload, self.interaction_id, self._token)

inherited property readonly bot: Client

A reference to the bot instance.

inherited property readonly expires_at: Timestamp

The timestamp the interaction is expected to expire at.

inherited property readonly expired: bool

Has the interaction expired yet?

async inherited method send_modal(self, modal)

Respond using a modal.

Parameters:

Name Type Description Default
modal Union[dict, Modal]

The modal to respond with

required

Returns:

Type Description
Union[dict, Modal]

The modal used.

Source code in naff/models/naff/context.py
async def send_modal(self, modal: Union[dict, "Modal"]) -> Union[dict, "Modal"]:
    """
    Respond using a modal.

    Args:
        modal: The modal to respond with

    Returns:
        The modal used.

    """
    payload = modal.to_dict() if not isinstance(modal, dict) else modal

    await self._client.http.post_initial_response(payload, self.interaction_id, self._token)

    self.responded = True
    return modal

classmethod method from_dict(data, client)

Create a context object from a dictionary.

Source code in naff/models/naff/context.py
@classmethod
def from_dict(cls, data: Dict, client: "Client") -> "ComponentContext":
    """Create a context object from a dictionary."""
    new_cls = super().from_dict(data, client)

    return new_cls

property readonly input_text: str

The text the user has entered so far.

async method send(self, choices)

Send your autocomplete choices to discord. Choices must be either a list of strings, or a dictionary following the following format:

1
2
3
4
    {
      "name": str,
      "value": str
    }
Where name is the text visible in Discord, and value is the data sent back to your client when that choice is chosen.

Parameters:

Name Type Description Default
choices List[Union[str, int, float, Dict[str, Union[str, int, float]]]]

25 choices the user can pick

required
Source code in naff/models/naff/context.py
async def send(self, choices: List[Union[str, int, float, Dict[str, Union[str, int, float]]]]) -> None:
    """
    Send your autocomplete choices to discord. Choices must be either a list of strings, or a dictionary following the following format:

    ```json
        {
          "name": str,
          "value": str
        }
    ```
    Where name is the text visible in Discord, and value is the data sent back to your client when that choice is
    chosen.

    Args:
        choices: 25 choices the user can pick

    """
    processed_choices = []
    for choice in choices:
        if isinstance(choice, (int, float)):
            processed_choices.append({"name": str(choice), "value": choice})
        elif isinstance(choice, dict):
            processed_choices.append(choice)
        else:
            choice = str(choice)
            processed_choices.append({"name": choice, "value": choice.replace(" ", "_")})

    payload = {"type": CallbackTypes.AUTOCOMPLETE_RESULT, "data": {"choices": processed_choices}}
    await self._client.http.post_initial_response(payload, self.interaction_id, self._token)

attrs class ModalContext (InteractionContext)

Attr attributes:

Name Type Description
invoke_target str

The name of the command to be invoked

command Optional[BaseCommand]

The command to be invoked

args List

The list of arguments to be passed to the command

kwargs Dict

The list of keyword arguments to be passed

author Union[Member, User]

The author of the message

channel TYPE_MESSAGEABLE_CHANNEL

The channel this was sent within

guild_id Snowflake_Type

The guild this was sent within, if not a DM

message Message

The message associated with this context

interaction_id str

The id of the interaction

target_id Snowflake_Type

The ID of the target, used for context menus to show what was clicked on

app_permissions Permissions

The permissions this interaction has

locale str

The selected language of the invoking user (https://discord.com/developers/docs/reference#locales)

guild_locale str

The guild's preferred locale

deferred bool

Is this interaction deferred?

responded bool

Have we responded to the interaction?

ephemeral bool

Are responses to this interaction hidden

resolved Resolved

Discord objects mentioned within this interaction

data Dict

The raw data of this interaction

Source code in naff/models/naff/context.py
@define
class ModalContext(InteractionContext):
    custom_id: str = field(default="")

    @classmethod
    def from_dict(cls, data: Dict, client: "Client") -> "ModalContext":
        new_cls = super().from_dict(data, client)

        new_cls.kwargs = {
            comp["components"][0]["custom_id"]: comp["components"][0]["value"] for comp in data["data"]["components"]
        }
        new_cls.custom_id = data["data"]["custom_id"]
        return new_cls

    @property
    def responses(self) -> dict[str, str]:
        """
        Get the responses to this modal.

        Returns:
            A dictionary of responses. Keys are the custom_ids of your components.
        """
        return self.kwargs

inherited property readonly bot: Client

A reference to the bot instance.

inherited property readonly expires_at: Timestamp

The timestamp the interaction is expected to expire at.

inherited property readonly expired: bool

Has the interaction expired yet?

async inherited method send_modal(self, modal)

Respond using a modal.

Parameters:

Name Type Description Default
modal Union[dict, Modal]

The modal to respond with

required

Returns:

Type Description
Union[dict, Modal]

The modal used.

Source code in naff/models/naff/context.py
async def send_modal(self, modal: Union[dict, "Modal"]) -> Union[dict, "Modal"]:
    """
    Respond using a modal.

    Args:
        modal: The modal to respond with

    Returns:
        The modal used.

    """
    payload = modal.to_dict() if not isinstance(modal, dict) else modal

    await self._client.http.post_initial_response(payload, self.interaction_id, self._token)

    self.responded = True
    return modal

async inherited method defer(self, ephemeral)

Defers the response, showing a loading state.

Parameters:

Name Type Description Default
ephemeral bool

Should the response be ephemeral

False
Source code in naff/models/naff/context.py
async def defer(self, ephemeral: bool = False) -> None:
    """
    Defers the response, showing a loading state.

    Args:
        ephemeral: Should the response be ephemeral

    """
    if self.deferred or self.responded:
        raise AlreadyDeferred("You have already responded to this interaction!")

    payload = {"type": CallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE}
    if ephemeral:
        payload["data"] = {"flags": MessageFlags.EPHEMERAL}

    await self._client.http.post_initial_response(payload, self.interaction_id, self._token)
    self.ephemeral = ephemeral
    self.deferred = True

async inherited method send(self, content, embeds, embed, components, stickers, allowed_mentions, reply_to, files, file, tts, suppress_embeds, flags, ephemeral)

Send a message.

Parameters:

Name Type Description Default
content Optional[str]

Message text content.

None
embeds Union[List[Union[Embed, dict]], Embed, dict]

Embedded rich content (up to 6000 characters).

None
embed Union[Embed, dict]

Embedded rich content (up to 6000 characters).

None
components Union[List[List[Union[BaseComponent, dict]]], List[Union[BaseComponent, dict]], BaseComponent, dict]

The components to include with the message.

None
stickers Union[List[Union[Sticker, Snowflake_Type]], Sticker, Snowflake_Type]

IDs of up to 3 stickers in the server to send in the message.

None
allowed_mentions Union[AllowedMentions, dict]

Allowed mentions for the message.

None
reply_to Union[MessageReference, Message, dict, Snowflake_Type]

Message to reference, must be from the same channel.

None
files Union[naff.models.discord.file.File, io.IOBase, BinaryIO, pathlib.Path, str, List[Union[naff.models.discord.file.File, io.IOBase, BinaryIO, pathlib.Path, str]]]

Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.

None
file Union[naff.models.discord.file.File, io.IOBase, BinaryIO, pathlib.Path, str]

Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.

None
tts bool

Should this message use Text To Speech.

False
suppress_embeds bool

Should embeds be suppressed on this send

False
flags Union[int, MessageFlags]

Message flags to apply.

None
ephemeral bool

Should this message be sent as ephemeral (hidden)

False

Returns:

Type Description
Message

New message object that was sent.

Source code in naff/models/naff/context.py
async def send(
    self,
    content: Optional[str] = None,
    embeds: Optional[Union[List[Union["Embed", dict]], Union["Embed", dict]]] = None,
    embed: Optional[Union["Embed", dict]] = None,
    components: Optional[
        Union[List[List[Union["BaseComponent", dict]]], List[Union["BaseComponent", dict]], "BaseComponent", dict]
    ] = None,
    stickers: Optional[Union[List[Union["Sticker", "Snowflake_Type"]], "Sticker", "Snowflake_Type"]] = None,
    allowed_mentions: Optional[Union["AllowedMentions", dict]] = None,
    reply_to: Optional[Union["MessageReference", "Message", dict, "Snowflake_Type"]] = None,
    files: Optional[Union[UPLOADABLE_TYPE, List[UPLOADABLE_TYPE]]] = None,
    file: Optional[UPLOADABLE_TYPE] = None,
    tts: bool = False,
    suppress_embeds: bool = False,
    flags: Optional[Union[int, "MessageFlags"]] = None,
    ephemeral: bool = False,
) -> "Message":
    """
    Send a message.

    Args:
        content: Message text content.
        embeds: Embedded rich content (up to 6000 characters).
        embed: Embedded rich content (up to 6000 characters).
        components: The components to include with the message.
        stickers: IDs of up to 3 stickers in the server to send in the message.
        allowed_mentions: Allowed mentions for the message.
        reply_to: Message to reference, must be from the same channel.
        files: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
        file: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
        tts: Should this message use Text To Speech.
        suppress_embeds: Should embeds be suppressed on this send
        flags: Message flags to apply.
        ephemeral bool: Should this message be sent as ephemeral (hidden)

    Returns:
        New message object that was sent.

    """
    if ephemeral:
        flags = MessageFlags.EPHEMERAL
        self.ephemeral = True

    if suppress_embeds:
        if isinstance(flags, int):
            flags = MessageFlags(flags)
        flags = flags | MessageFlags.SUPPRESS_EMBEDS

    return await super().send(
        content,
        embeds=embeds,
        embed=embed,
        components=components,
        stickers=stickers,
        allowed_mentions=allowed_mentions,
        reply_to=reply_to,
        files=files,
        file=file,
        tts=tts,
        flags=flags,
    )

inherited property readonly target: Absent[Member | User | Message]

For context menus, this will be the object of which was clicked on.

classmethod method from_dict(data, client)

Create a context object from a dictionary.

Source code in naff/models/naff/context.py
@classmethod
def from_dict(cls, data: Dict, client: "Client") -> "ModalContext":
    new_cls = super().from_dict(data, client)

    new_cls.kwargs = {
        comp["components"][0]["custom_id"]: comp["components"][0]["value"] for comp in data["data"]["components"]
    }
    new_cls.custom_id = data["data"]["custom_id"]
    return new_cls

property readonly responses: dict

Get the responses to this modal.

Returns:

Type Description
dict

A dictionary of responses. Keys are the custom_ids of your components.

attrs class PrefixedContext (Context, SendMixin)

Attr attributes:

Name Type Description
invoke_target str

The name of the command to be invoked

command Optional[BaseCommand]

The command to be invoked

args List

The list of arguments to be passed to the command

kwargs Dict

The list of keyword arguments to be passed

author Union[Member, User]

The author of the message

channel TYPE_MESSAGEABLE_CHANNEL

The channel this was sent within

guild_id Snowflake_Type

The guild this was sent within, if not a DM

message Message

The message associated with this context

prefix str

The prefix used to invoke this command

Source code in naff/models/naff/context.py
@define
class PrefixedContext(Context, SendMixin):
    prefix: str = field(default=MISSING, metadata=docs("The prefix used to invoke this command"))

    @classmethod
    def from_message(cls, client: "Client", message: "Message") -> "PrefixedContext":
        new_cls = cls(
            client=client,
            message=message,
            author=message.author,
            channel=message.channel,
            guild_id=message._guild_id,
        )
        return new_cls

    @property
    def content_parameters(self) -> str:
        return self.message.content.removeprefix(f"{self.prefix}{self.invoke_target}").strip()

    async def reply(
        self,
        content: Optional[str] = None,
        embeds: Optional[Union[List[Union["Embed", dict]], Union["Embed", dict]]] = None,
        embed: Optional[Union["Embed", dict]] = None,
        **kwargs,
    ) -> "Message":
        """Reply to this message, takes all the same attributes as `send`."""
        return await self.send(content=content, reply_to=self.message, embeds=embeds or embed, **kwargs)

    async def _send_http_request(
        self, message_payload: Union[dict, "FormData"], files: list["UPLOADABLE_TYPE"] | None = None
    ) -> dict:
        return await self._client.http.create_message(message_payload, self.channel.id, files=files)

async inherited method send(self, content, embeds, embed, components, stickers, allowed_mentions, reply_to, files, file, tts, suppress_embeds, flags, delete_after, **kwargs)

Send a message.

Parameters:

Name Type Description Default
content Optional[str]

Message text content.

None
embeds Union[List[Union[Embed, dict]], Embed, dict]

Embedded rich content (up to 6000 characters).

None
embed Union[Embed, dict]

Embedded rich content (up to 6000 characters).

None
components Union[List[List[Union[BaseComponent, dict]]], List[Union[BaseComponent, dict]], BaseComponent, dict]

The components to include with the message.

None
stickers Union[List[Union[Sticker, Snowflake_Type]], Sticker, Snowflake_Type]

IDs of up to 3 stickers in the server to send in the message.

None
allowed_mentions Union[AllowedMentions, dict]

Allowed mentions for the message.

None
reply_to Union[MessageReference, Message, dict, Snowflake_Type]

Message to reference, must be from the same channel.

None
files Union[UPLOADABLE_TYPE, List[UPLOADABLE_TYPE]]

Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.

None
file Optional[UPLOADABLE_TYPE]

Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.

None
tts bool

Should this message use Text To Speech.

False
suppress_embeds bool

Should embeds be suppressed on this send

False
flags Union[int, MessageFlags]

Message flags to apply.

None
delete_after Optional[float]

Delete message after this many seconds.

None

Returns:

Type Description
Message

New message object that was sent.

Source code in naff/models/naff/context.py
async def send(
    self,
    content: Optional[str] = None,
    embeds: Optional[Union[List[Union["Embed", dict]], Union["Embed", dict]]] = None,
    embed: Optional[Union["Embed", dict]] = None,
    components: Optional[
        Union[List[List[Union["BaseComponent", dict]]], List[Union["BaseComponent", dict]], "BaseComponent", dict]
    ] = None,
    stickers: Optional[Union[List[Union["Sticker", "Snowflake_Type"]], "Sticker", "Snowflake_Type"]] = None,
    allowed_mentions: Optional[Union["AllowedMentions", dict]] = None,
    reply_to: Optional[Union["MessageReference", "Message", dict, "Snowflake_Type"]] = None,
    files: Optional[Union["UPLOADABLE_TYPE", List["UPLOADABLE_TYPE"]]] = None,
    file: Optional["UPLOADABLE_TYPE"] = None,
    tts: bool = False,
    suppress_embeds: bool = False,
    flags: Optional[Union[int, "MessageFlags"]] = None,
    delete_after: Optional[float] = None,
    **kwargs,
) -> "Message":
    """
    Send a message.

    Args:
        content: Message text content.
        embeds: Embedded rich content (up to 6000 characters).
        embed: Embedded rich content (up to 6000 characters).
        components: The components to include with the message.
        stickers: IDs of up to 3 stickers in the server to send in the message.
        allowed_mentions: Allowed mentions for the message.
        reply_to: Message to reference, must be from the same channel.
        files: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
        file: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
        tts: Should this message use Text To Speech.
        suppress_embeds: Should embeds be suppressed on this send
        flags: Message flags to apply.
        delete_after: Delete message after this many seconds.

    Returns:
        New message object that was sent.

    """
    if not content and not (embeds or embed) and not (files or file) and not stickers:
        raise errors.EmptyMessageException(
            "You cannot send a message without any content, embeds, files, or stickers"
        )

    if suppress_embeds:
        if isinstance(flags, int):
            flags = MessageFlags(flags)
        flags = flags | MessageFlags.SUPPRESS_EMBEDS

    message_payload = models.discord.message.process_message_payload(
        content=content,
        embeds=embeds or embed,
        components=components,
        stickers=stickers,
        allowed_mentions=allowed_mentions,
        reply_to=reply_to,
        tts=tts,
        flags=flags,
        **kwargs,
    )

    message_data = await self._send_http_request(message_payload, files=files or file)
    if message_data:
        message = self._client.cache.place_message_data(message_data)
        if delete_after:
            await message.delete(delay=delete_after)
        return message

inherited property readonly bot: Client

A reference to the bot instance.

async method reply(self, content, embeds, embed, **kwargs)

Reply to this message, takes all the same attributes as send.

Source code in naff/models/naff/context.py
async def reply(
    self,
    content: Optional[str] = None,
    embeds: Optional[Union[List[Union["Embed", dict]], Union["Embed", dict]]] = None,
    embed: Optional[Union["Embed", dict]] = None,
    **kwargs,
) -> "Message":
    """Reply to this message, takes all the same attributes as `send`."""
    return await self.send(content=content, reply_to=self.message, embeds=embeds or embed, **kwargs)

attrs class HybridContext (Context)

Represents the context for hybrid commands, a slash command that can also be used as a prefixed command.

This attempts to create a compatibility layer to allow contexts for an interaction or a message to be used seamlessly.

Attr attributes:

Name Type Description
invoke_target str

The name of the command to be invoked

command Optional[BaseCommand]

The command to be invoked

args List

The list of arguments to be passed to the command

kwargs Dict

The list of keyword arguments to be passed

author Union[Member, User]

The author of the message

channel TYPE_MESSAGEABLE_CHANNEL

The channel this was sent within

guild_id Snowflake_Type

The guild this was sent within, if not a DM

message Message

The message associated with this context

deferred bool

Is this context deferred?

responded bool

Have we responded to this?

app_permissions Permissions

The permissions this context has

Source code in naff/models/naff/context.py
@define
class HybridContext(Context):
    """
    Represents the context for hybrid commands, a slash command that can also be used as a prefixed command.

    This attempts to create a compatibility layer to allow contexts for an interaction or a message to be used seamlessly.
    """

    deferred: bool = field(default=False, metadata=docs("Is this context deferred?"))
    responded: bool = field(default=False, metadata=docs("Have we responded to this?"))
    app_permissions: Permissions = field(
        default=0, converter=Permissions, metadata=docs("The permissions this context has")
    )

    _interaction_context: Optional[InteractionContext] = field(default=None)
    _prefixed_context: Optional[PrefixedContext] = field(default=None)

    @classmethod
    def from_interaction_context(cls, context: InteractionContext) -> "HybridContext":
        return cls(
            client=context._client,  # type: ignore
            interaction_context=context,  # type: ignore
            invoke_target=context.invoke_target,
            command=context.command,
            args=context.args,
            kwargs=context.kwargs,
            author=context.author,
            channel=context.channel,
            guild_id=context.guild_id,
            deferred=context.deferred,
            responded=context.responded,
            app_permissions=context.app_permissions,
        )

    @classmethod
    def from_prefixed_context(cls, context: PrefixedContext) -> "HybridContext":
        # this is a "best guess" on what the permissions are
        # this may or may not be totally accurate
        if hasattr(context.channel, "permissions_for"):
            app_permissions = context.channel.permissions_for(context.guild.me)  # type: ignore
        elif context.channel.type in {10, 11, 12}:  # it's a thread
            app_permissions = context.channel.parent_channel.permissions_for(context.guild.me)  # type: ignore
        else:
            # this is what happens with interaction contexts in dms
            app_permissions = 0

        return cls(
            client=context._client,  # type: ignore
            prefixed_context=context,  # type: ignore
            invoke_target=context.invoke_target,
            command=context.command,
            args=context.args,
            kwargs=context.kwargs,  # this is usually empty
            author=context.author,
            channel=context.channel,
            guild_id=context.guild_id,
            message=context.message,
            app_permissions=app_permissions,
        )

    @property
    def inner_context(self) -> InteractionContext | PrefixedContext:
        """
        Returns the context powering the current hybrid context.

        This can be used for scope-specific actions, like sending modals in an interaction.
        """
        return self._interaction_context or self._prefixed_context  # type: ignore

    @property
    def ephemeral(self) -> bool:
        """Returns if responses to this interaction are ephemeral, if this is an interaction. Otherwise, returns False."""
        return self._interaction_context.ephemeral if self._interaction_context else False

    @property
    def expires_at(self) -> Optional[Timestamp]:
        """The timestamp the context is expected to expire at, or None if the context never expires."""
        if not self._interaction_context:
            return None

        if self.responded:
            return Timestamp.from_snowflake(self._interaction_context.interaction_id) + datetime.timedelta(minutes=15)
        return Timestamp.from_snowflake(self._interaction_context.interaction_id) + datetime.timedelta(seconds=3)

    @property
    def expired(self) -> bool:
        """Has the context expired yet?"""
        return Timestamp.utcnow() >= self.expires_at if self.expires_at else False

    @property
    def invoked_name(self) -> str:
        return (
            self.command.get_localised_name(self._interaction_context.locale)
            if self._interaction_context
            else self.invoke_target
        )

    async def defer(self, ephemeral: bool = False) -> None:
        """
        Either defers the response (if used in an interaction) or triggers a typing indicator for 10 seconds (if used for messages).

        Args:
            ephemeral: Should the response be ephemeral? Only applies to responses for interactions.

        """
        if self._interaction_context:
            await self._interaction_context.defer(ephemeral=ephemeral)
        else:
            await self.channel.trigger_typing()

        self.deferred = True

    async def reply(
        self,
        content: Optional[str] = None,
        embeds: Optional[Union[List[Union["Embed", dict]], Union["Embed", dict]]] = None,
        embed: Optional[Union["Embed", dict]] = None,
        **kwargs,
    ) -> "Message":
        """
        Reply to this message, takes all the same attributes as `send`.

        For interactions, this functions the same as `send`.
        """
        kwargs = locals()
        kwargs.pop("self")
        extra_kwargs = kwargs.pop("kwargs")
        kwargs |= extra_kwargs

        if self._interaction_context:
            result = await self._interaction_context.send(**kwargs)
        else:
            kwargs.pop("ephemeral", None)
            result = await self._prefixed_context.reply(**kwargs)  # type: ignore

        self.responded = True
        return result

    async def send(
        self,
        content: Optional[str] = None,
        embeds: Optional[Union[List[Union["Embed", dict]], Union["Embed", dict]]] = None,
        embed: Optional[Union["Embed", dict]] = None,
        components: Optional[
            Union[
                List[List[Union["BaseComponent", dict]]],
                List[Union["BaseComponent", dict]],
                "BaseComponent",
                dict,
            ]
        ] = None,
        stickers: Optional[Union[List[Union["Sticker", "Snowflake_Type"]], "Sticker", "Snowflake_Type"]] = None,
        allowed_mentions: Optional[Union["AllowedMentions", dict]] = None,
        reply_to: Optional[Union["MessageReference", "Message", dict, "Snowflake_Type"]] = None,
        file: Optional[Union["File", "IOBase", "Path", str]] = None,
        tts: bool = False,
        flags: Optional[Union[int, "MessageFlags"]] = None,
        ephemeral: bool = False,
        **kwargs,
    ) -> "Message":
        """
        Send a message.

        Args:
            content: Message text content.
            embeds: Embedded rich content (up to 6000 characters).
            embed: Embedded rich content (up to 6000 characters).
            components: The components to include with the message.
            stickers: IDs of up to 3 stickers in the server to send in the message.
            allowed_mentions: Allowed mentions for the message.
            reply_to: Message to reference, must be from the same channel.
            files: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
            file: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
            tts: Should this message use Text To Speech.
            suppress_embeds: Should embeds be suppressed on this send
            flags: Message flags to apply.
            ephemeral: Should this message be sent as ephemeral (hidden) - only works with interactions.

        Returns:
            New message object that was sent.

        """
        kwargs = locals()
        kwargs.pop("self")
        extra_kwargs = kwargs.pop("kwargs")
        kwargs |= extra_kwargs

        if self._interaction_context:
            result = await self._interaction_context.send(**kwargs)
        else:
            kwargs.pop("ephemeral", None)
            result = await self._prefixed_context.send(**kwargs)  # type: ignore

        self.responded = True
        return result

inherited property readonly bot: Client

A reference to the bot instance.

property readonly inner_context: naff.models.naff.context.InteractionContext | naff.models.naff.context.PrefixedContext

Returns the context powering the current hybrid context.

This can be used for scope-specific actions, like sending modals in an interaction.

property readonly ephemeral: bool

Returns if responses to this interaction are ephemeral, if this is an interaction. Otherwise, returns False.

property readonly expires_at: Optional[naff.models.discord.timestamp.Timestamp]

The timestamp the context is expected to expire at, or None if the context never expires.

property readonly expired: bool

Has the context expired yet?

async method defer(self, ephemeral)

Either defers the response (if used in an interaction) or triggers a typing indicator for 10 seconds (if used for messages).

Parameters:

Name Type Description Default
ephemeral bool

Should the response be ephemeral? Only applies to responses for interactions.

False
Source code in naff/models/naff/context.py
async def defer(self, ephemeral: bool = False) -> None:
    """
    Either defers the response (if used in an interaction) or triggers a typing indicator for 10 seconds (if used for messages).

    Args:
        ephemeral: Should the response be ephemeral? Only applies to responses for interactions.

    """
    if self._interaction_context:
        await self._interaction_context.defer(ephemeral=ephemeral)
    else:
        await self.channel.trigger_typing()

    self.deferred = True

async method reply(self, content, embeds, embed, **kwargs)

Reply to this message, takes all the same attributes as send.

For interactions, this functions the same as send.

Source code in naff/models/naff/context.py
async def reply(
    self,
    content: Optional[str] = None,
    embeds: Optional[Union[List[Union["Embed", dict]], Union["Embed", dict]]] = None,
    embed: Optional[Union["Embed", dict]] = None,
    **kwargs,
) -> "Message":
    """
    Reply to this message, takes all the same attributes as `send`.

    For interactions, this functions the same as `send`.
    """
    kwargs = locals()
    kwargs.pop("self")
    extra_kwargs = kwargs.pop("kwargs")
    kwargs |= extra_kwargs

    if self._interaction_context:
        result = await self._interaction_context.send(**kwargs)
    else:
        kwargs.pop("ephemeral", None)
        result = await self._prefixed_context.reply(**kwargs)  # type: ignore

    self.responded = True
    return result

async method send(self, content, embeds, embed, components, stickers, allowed_mentions, reply_to, file, tts, flags, ephemeral, **kwargs)

Send a message.

Parameters:

Name Type Description Default
content Optional[str]

Message text content.

None
embeds Union[List[Union[Embed, dict]], Embed, dict]

Embedded rich content (up to 6000 characters).

None
embed Union[Embed, dict]

Embedded rich content (up to 6000 characters).

None
components Union[List[List[Union[BaseComponent, dict]]], List[Union[BaseComponent, dict]], BaseComponent, dict]

The components to include with the message.

None
stickers Union[List[Union[Sticker, Snowflake_Type]], Sticker, Snowflake_Type]

IDs of up to 3 stickers in the server to send in the message.

None
allowed_mentions Union[AllowedMentions, dict]

Allowed mentions for the message.

None
reply_to Union[MessageReference, Message, dict, Snowflake_Type]

Message to reference, must be from the same channel.

None
files

Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.

required
file Union[File, IOBase, Path, str]

Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.

None
tts bool

Should this message use Text To Speech.

False
suppress_embeds

Should embeds be suppressed on this send

required
flags Union[int, MessageFlags]

Message flags to apply.

None
ephemeral bool

Should this message be sent as ephemeral (hidden) - only works with interactions.

False

Returns:

Type Description
Message

New message object that was sent.

Source code in naff/models/naff/context.py
async def send(
    self,
    content: Optional[str] = None,
    embeds: Optional[Union[List[Union["Embed", dict]], Union["Embed", dict]]] = None,
    embed: Optional[Union["Embed", dict]] = None,
    components: Optional[
        Union[
            List[List[Union["BaseComponent", dict]]],
            List[Union["BaseComponent", dict]],
            "BaseComponent",
            dict,
        ]
    ] = None,
    stickers: Optional[Union[List[Union["Sticker", "Snowflake_Type"]], "Sticker", "Snowflake_Type"]] = None,
    allowed_mentions: Optional[Union["AllowedMentions", dict]] = None,
    reply_to: Optional[Union["MessageReference", "Message", dict, "Snowflake_Type"]] = None,
    file: Optional[Union["File", "IOBase", "Path", str]] = None,
    tts: bool = False,
    flags: Optional[Union[int, "MessageFlags"]] = None,
    ephemeral: bool = False,
    **kwargs,
) -> "Message":
    """
    Send a message.

    Args:
        content: Message text content.
        embeds: Embedded rich content (up to 6000 characters).
        embed: Embedded rich content (up to 6000 characters).
        components: The components to include with the message.
        stickers: IDs of up to 3 stickers in the server to send in the message.
        allowed_mentions: Allowed mentions for the message.
        reply_to: Message to reference, must be from the same channel.
        files: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
        file: Files to send, the path, bytes or File() instance, defaults to None. You may have up to 10 files.
        tts: Should this message use Text To Speech.
        suppress_embeds: Should embeds be suppressed on this send
        flags: Message flags to apply.
        ephemeral: Should this message be sent as ephemeral (hidden) - only works with interactions.

    Returns:
        New message object that was sent.

    """
    kwargs = locals()
    kwargs.pop("self")
    extra_kwargs = kwargs.pop("kwargs")
    kwargs |= extra_kwargs

    if self._interaction_context:
        result = await self._interaction_context.send(**kwargs)
    else:
        kwargs.pop("ephemeral", None)
        result = await self._prefixed_context.send(**kwargs)  # type: ignore

    self.responded = True
    return result

class SendableContext (Protocol)

A protocol that supports any context that can send messages.

Use it to type hint something that accepts both PrefixedContext and InteractionContext.

Source code in naff/models/naff/context.py
@runtime_checkable
class SendableContext(Protocol):
    """
    A protocol that supports any context that can send messages.

    Use it to type hint something that accepts both PrefixedContext and InteractionContext.
    """

    channel: "TYPE_MESSAGEABLE_CHANNEL"
    invoke_target: str

    author: Union["Member", "User"]
    guild_id: "Snowflake_Type"
    message: "Message"

    @property
    def bot(self) -> "Client":
        ...

    @property
    def guild(self) -> Optional["Guild"]:
        ...

    async def send(
        self,
        content: Optional[str] = None,
        embeds: Optional[Union[List[Union["Embed", dict]], Union["Embed", dict]]] = None,
        components: Optional[
            Union[
                List[List[Union["BaseComponent", dict]]],
                List[Union["BaseComponent", dict]],
                "BaseComponent",
                dict,
            ]
        ] = None,
        stickers: Optional[Union[List[Union["Sticker", "Snowflake_Type"]], "Sticker", "Snowflake_Type"]] = None,
        allowed_mentions: Optional[Union["AllowedMentions", dict]] = None,
        reply_to: Optional[Union["MessageReference", "Message", dict, "Snowflake_Type"]] = None,
        file: Optional[Union["File", "IOBase", "Path", str]] = None,
        tts: bool = False,
        flags: Optional[Union[int, "MessageFlags"]] = None,
        **kwargs: Any,
    ) -> "Message":
        ...