Skip to content

Webhooks

class WebhookTypes (IntEnum)

An enumeration.

Source code in naff/models/discord/webhooks.py
class WebhookTypes(IntEnum):
    INCOMING = 1
    """Incoming Webhooks can post messages to channels with a generated token"""
    CHANNEL_FOLLOWER = 2
    """Channel Follower Webhooks are internal webhooks used with Channel Following to post new messages into channels"""
    APPLICATION = 3
    """Application webhooks are webhooks used with Interactions"""

APPLICATION

Application webhooks are webhooks used with Interactions

CHANNEL_FOLLOWER

Channel Follower Webhooks are internal webhooks used with Channel Following to post new messages into channels

INCOMING

Incoming Webhooks can post messages to channels with a generated token

attrs class Webhook (DiscordObject, SendMixin)

Attr attributes:

Name Type Description
id int

Discord unique snowflake ID

type WebhookTypes

The type of webhook

application_id Optional[Snowflake_Type]

the bot/OAuth2 application that created this webhook

guild_id Optional[Snowflake_Type]

the guild id this webhook is for, if any

channel_id Optional[Snowflake_Type]

the channel id this webhook is for, if any

user_id Optional[Snowflake_Type]

the user this webhook was created by

name Optional[str]

the default name of the webhook

avatar Optional[str]

the default user avatar hash of the webhook

token str

the secure token of the webhook (returned for Incoming Webhooks)

url Optional[str]

the url used for executing the webhook (returned by the webhooks OAuth2 flow)

source_guild_id Optional[Snowflake_Type]

the guild of the channel that this webhook is following (returned for Channel Follower Webhooks)

source_channel_id Optional[Snowflake_Type]

the channel that this webhook is following (returned for Channel Follower Webhooks)

Source code in naff/models/discord/webhooks.py
@define()
class Webhook(DiscordObject, SendMixin):
    type: WebhookTypes = field()
    """The type of webhook"""

    application_id: Optional["Snowflake_Type"] = field(default=None)
    """the bot/OAuth2 application that created this webhook"""

    guild_id: Optional["Snowflake_Type"] = field(default=None)
    """the guild id this webhook is for, if any"""
    channel_id: Optional["Snowflake_Type"] = field(default=None)
    """the channel id this webhook is for, if any"""
    user_id: Optional["Snowflake_Type"] = field(default=None)
    """the user this webhook was created by"""

    name: Optional[str] = field(default=None)
    """the default name of the webhook"""
    avatar: Optional[str] = field(default=None)
    """the default user avatar hash of the webhook"""
    token: str = field(default=MISSING)
    """the secure token of the webhook (returned for Incoming Webhooks)"""
    url: Optional[str] = field(default=None)
    """the url used for executing the webhook (returned by the webhooks OAuth2 flow)"""

    source_guild_id: Optional["Snowflake_Type"] = field(default=None)
    """the guild of the channel that this webhook is following (returned for Channel Follower Webhooks)"""
    source_channel_id: Optional["Snowflake_Type"] = field(default=None)
    """the channel that this webhook is following (returned for Channel Follower Webhooks)"""

    @classmethod
    def from_url(cls, url: str, client: "Client") -> "Webhook":
        """
        Webhook object from a URL.

        Args:
            client: The client to use to make the request.
            url: Webhook URL

        Returns:
            A Webhook object.

        """
        match = re.search(r"discord(?:app)?\.com/api/webhooks/(?P<id>[0-9]{17,})/(?P<token>[\w\-.]{60,68})", url)
        if match is None:
            raise ValueError("Invalid webhook URL given.")

        data: Dict[str, Any] = match.groupdict()
        data["type"] = WebhookTypes.INCOMING
        return cls.from_dict(data, client)

    @classmethod
    async def create(
        cls,
        client: "Client",
        channel: Union["Snowflake_Type", "TYPE_MESSAGEABLE_CHANNEL"],
        name: str,
        avatar: Absent["UPLOADABLE_TYPE"] = MISSING,
    ) -> "Webhook":
        """
        Create a webhook.

        Args:
            client: The bot's client
            channel: The channel to create the webhook in
            name: The name of the webhook
            avatar: An optional default avatar to use

        Returns:
            New webhook object

        Raises:
            ValueError: If you try to name the webhook "Clyde"

        """
        if name.lower() == "clyde":
            raise ValueError('Webhook names cannot be "Clyde"')

        if not isinstance(channel, (str, int)):
            channel = to_snowflake(channel)

        if avatar:
            avatar = to_image_data(avatar)

        data = await client.http.create_webhook(channel, name, avatar)

        new_cls = cls.from_dict(data, client)

        return new_cls

    @classmethod
    def _process_dict(cls, data: Dict[str, Any], client: "Client") -> Dict[str, Any]:
        if data.get("user"):
            user = client.cache.place_user_data(data.pop("user"))
            data["user_id"] = user.id
        return data

    async def edit(
        self,
        name: Absent[str] = MISSING,
        avatar: Absent["UPLOADABLE_TYPE"] = MISSING,
        channel_id: Absent["Snowflake_Type"] = MISSING,
    ) -> None:
        """
        Edit this webhook.

        Args:
            name: The default name of the webhook.
            avatar: The image for the default webhook avatar.
            channel_id: The new channel id this webhook should be moved to.

        Raises:
            ValueError: If you try to name the webhook "Clyde"

        """
        if name.lower() == "clyde":
            raise ValueError('Webhook names cannot be "Clyde"')

        data = await self._client.http.modify_webhook(
            self.id, name, to_image_data(avatar), to_optional_snowflake(channel_id), self.token
        )
        self.update_from_dict(data)

    async def delete(self) -> None:
        """Delete this webhook."""
        await self._client.http.delete_webhook(self.id, self.token)

    async def send(
        self,
        content: Optional[str] = None,
        embed: Optional[Union["Embed", dict]] = 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,
        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,
        username: str = None,
        avatar_url: str = None,
        wait: bool = False,
        thread: "Snowflake_Type" = None,
        **kwargs,
    ) -> Optional["Message"]:
        """
        Send a message as this webhook.

        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.
            username: The username to use
            avatar_url: The url of an image to use as the avatar
            wait: Waits for confirmation of delivery. Set this to True if you intend to edit the message
            thread: Send this webhook to a thread channel

        Returns:
            New message object that was sent if `wait` is set to True

        """
        if not self.token:
            raise ForeignWebhookException("You cannot send messages with a webhook without a token!")

        if not content and not (embeds or embed) and not (files or file) and not stickers:
            raise 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 = 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,
            username=username,
            avatar_url=avatar_url,
            **kwargs,
        )

        message_data = await self._client.http.execute_webhook(
            self.id, self.token, message_payload, wait, to_optional_snowflake(thread), files=files or file
        )
        if message_data:
            return self._client.cache.place_message_data(message_data)

    async def edit_message(
        self,
        message: Union["Message", "Snowflake_Type"],
        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,
        files: Optional[Union["UPLOADABLE_TYPE", List["UPLOADABLE_TYPE"]]] = None,
        file: Optional["UPLOADABLE_TYPE"] = None,
        tts: bool = False,
        flags: Optional[Union[int, "MessageFlags"]] = None,
    ) -> Optional["Message"]:
        """
        Edit a message as this webhook.

        Args:
            message: Message to edit
            content: Message text content.
            embeds: 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.
            flags: Message flags to apply.

        Returns:
            Updated message object that was sent if `wait` is set to True

        """
        message_payload = process_message_payload(
            content=content,
            embeds=embeds,
            components=components,
            stickers=stickers,
            allowed_mentions=allowed_mentions,
            reply_to=reply_to,
            tts=tts,
            flags=flags,
        )
        msg_data = await self._client.http.edit_webhook_message(
            self.id, self.token, to_snowflake(message), message_payload, files=files or file
        )
        if msg_data:
            return self._client.cache.place_message_data(msg_data)

inherited method update_from_dict(self, data)

Updates object attribute(s) with new json data received from discord api.

Parameters:

Name Type Description Default
data

The json data received from discord api.

required

Returns:

Type Description
~T

The updated object class instance.

Source code in naff/models/discord/webhooks.py
def update_from_dict(self, data) -> T:
    data = self._process_dict(data, self._client)
    for key, value in self._filter_kwargs(data, self._get_keys()).items():
        # todo improve
        setattr(self, key, value)

    return self

classmethod method from_url(url, client)

Webhook object from a URL.

Parameters:

Name Type Description Default
client Client

The client to use to make the request.

required
url str

Webhook URL

required

Returns:

Type Description
Webhook

A Webhook object.

Source code in naff/models/discord/webhooks.py
@classmethod
def from_url(cls, url: str, client: "Client") -> "Webhook":
    """
    Webhook object from a URL.

    Args:
        client: The client to use to make the request.
        url: Webhook URL

    Returns:
        A Webhook object.

    """
    match = re.search(r"discord(?:app)?\.com/api/webhooks/(?P<id>[0-9]{17,})/(?P<token>[\w\-.]{60,68})", url)
    if match is None:
        raise ValueError("Invalid webhook URL given.")

    data: Dict[str, Any] = match.groupdict()
    data["type"] = WebhookTypes.INCOMING
    return cls.from_dict(data, client)

inherited property readonly created_at: models.Timestamp

Returns a timestamp representing the date-time this discord object was created.

:Returns:

async classmethod method create(client, channel, name, avatar)

Create a webhook.

Parameters:

Name Type Description Default
client Client

The bot's client

required
channel Union[Snowflake_Type, TYPE_MESSAGEABLE_CHANNEL]

The channel to create the webhook in

required
name str

The name of the webhook

required
avatar Union[UPLOADABLE_TYPE, naff.client.const.Missing]

An optional default avatar to use

Missing

Returns:

Type Description
Webhook

New webhook object

Exceptions:

Type Description
ValueError

If you try to name the webhook "Clyde"

Source code in naff/models/discord/webhooks.py
@classmethod
async def create(
    cls,
    client: "Client",
    channel: Union["Snowflake_Type", "TYPE_MESSAGEABLE_CHANNEL"],
    name: str,
    avatar: Absent["UPLOADABLE_TYPE"] = MISSING,
) -> "Webhook":
    """
    Create a webhook.

    Args:
        client: The bot's client
        channel: The channel to create the webhook in
        name: The name of the webhook
        avatar: An optional default avatar to use

    Returns:
        New webhook object

    Raises:
        ValueError: If you try to name the webhook "Clyde"

    """
    if name.lower() == "clyde":
        raise ValueError('Webhook names cannot be "Clyde"')

    if not isinstance(channel, (str, int)):
        channel = to_snowflake(channel)

    if avatar:
        avatar = to_image_data(avatar)

    data = await client.http.create_webhook(channel, name, avatar)

    new_cls = cls.from_dict(data, client)

    return new_cls

inherited method to_dict(self)

Exports object into dictionary representation, ready to be sent to discord api.

Returns:

Type Description
Dict[str, Any]

The exported dictionary.

Source code in naff/models/discord/webhooks.py
def to_dict(self) -> Dict[str, Any]:
    """
    Exports object into dictionary representation, ready to be sent to discord api.

    Returns:
        The exported dictionary.

    """
    self._check_object()
    return serializer.to_dict(self)

async method edit(self, name, avatar, channel_id)

Edit this webhook.

Parameters:

Name Type Description Default
name Union[str, naff.client.const.Missing]

The default name of the webhook.

Missing
avatar Union[UPLOADABLE_TYPE, naff.client.const.Missing]

The image for the default webhook avatar.

Missing
channel_id Union[Snowflake_Type, naff.client.const.Missing]

The new channel id this webhook should be moved to.

Missing

Exceptions:

Type Description
ValueError

If you try to name the webhook "Clyde"

Source code in naff/models/discord/webhooks.py
async def edit(
    self,
    name: Absent[str] = MISSING,
    avatar: Absent["UPLOADABLE_TYPE"] = MISSING,
    channel_id: Absent["Snowflake_Type"] = MISSING,
) -> None:
    """
    Edit this webhook.

    Args:
        name: The default name of the webhook.
        avatar: The image for the default webhook avatar.
        channel_id: The new channel id this webhook should be moved to.

    Raises:
        ValueError: If you try to name the webhook "Clyde"

    """
    if name.lower() == "clyde":
        raise ValueError('Webhook names cannot be "Clyde"')

    data = await self._client.http.modify_webhook(
        self.id, name, to_image_data(avatar), to_optional_snowflake(channel_id), self.token
    )
    self.update_from_dict(data)

async method delete(self)

Delete this webhook.

Source code in naff/models/discord/webhooks.py
async def delete(self) -> None:
    """Delete this webhook."""
    await self._client.http.delete_webhook(self.id, self.token)

async method send(self, content, embed, embeds, components, stickers, allowed_mentions, reply_to, files, file, tts, suppress_embeds, flags, username, avatar_url, wait, thread, **kwargs)

Send a message as this webhook.

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
username str

The username to use

None
avatar_url str

The url of an image to use as the avatar

None
wait bool

Waits for confirmation of delivery. Set this to True if you intend to edit the message

False
thread Snowflake_Type

Send this webhook to a thread channel

None

Returns:

Type Description
Optional[Message]

New message object that was sent if wait is set to True

Source code in naff/models/discord/webhooks.py
async def send(
    self,
    content: Optional[str] = None,
    embed: Optional[Union["Embed", dict]] = 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,
    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,
    username: str = None,
    avatar_url: str = None,
    wait: bool = False,
    thread: "Snowflake_Type" = None,
    **kwargs,
) -> Optional["Message"]:
    """
    Send a message as this webhook.

    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.
        username: The username to use
        avatar_url: The url of an image to use as the avatar
        wait: Waits for confirmation of delivery. Set this to True if you intend to edit the message
        thread: Send this webhook to a thread channel

    Returns:
        New message object that was sent if `wait` is set to True

    """
    if not self.token:
        raise ForeignWebhookException("You cannot send messages with a webhook without a token!")

    if not content and not (embeds or embed) and not (files or file) and not stickers:
        raise 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 = 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,
        username=username,
        avatar_url=avatar_url,
        **kwargs,
    )

    message_data = await self._client.http.execute_webhook(
        self.id, self.token, message_payload, wait, to_optional_snowflake(thread), files=files or file
    )
    if message_data:
        return self._client.cache.place_message_data(message_data)

async method edit_message(self, message, content, embeds, components, stickers, allowed_mentions, reply_to, files, file, tts, flags)

Edit a message as this webhook.

Parameters:

Name Type Description Default
message Union[Message, Snowflake_Type]

Message to edit

required
content Optional[str]

Message text content.

None
embeds Union[List[Union[Embed, dict]], 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
flags Union[int, MessageFlags]

Message flags to apply.

None

Returns:

Type Description
Optional[Message]

Updated message object that was sent if wait is set to True

Source code in naff/models/discord/webhooks.py
async def edit_message(
    self,
    message: Union["Message", "Snowflake_Type"],
    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,
    files: Optional[Union["UPLOADABLE_TYPE", List["UPLOADABLE_TYPE"]]] = None,
    file: Optional["UPLOADABLE_TYPE"] = None,
    tts: bool = False,
    flags: Optional[Union[int, "MessageFlags"]] = None,
) -> Optional["Message"]:
    """
    Edit a message as this webhook.

    Args:
        message: Message to edit
        content: Message text content.
        embeds: 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.
        flags: Message flags to apply.

    Returns:
        Updated message object that was sent if `wait` is set to True

    """
    message_payload = process_message_payload(
        content=content,
        embeds=embeds,
        components=components,
        stickers=stickers,
        allowed_mentions=allowed_mentions,
        reply_to=reply_to,
        tts=tts,
        flags=flags,
    )
    msg_data = await self._client.http.edit_webhook_message(
        self.id, self.token, to_snowflake(message), message_payload, files=files or file
    )
    if msg_data:
        return self._client.cache.place_message_data(msg_data)