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 |
|
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":
...