Back to top

hikari.webhooks

Application and entities that are used to describe webhooks on Discord.

View Source
# -*- coding: utf-8 -*-
# cython: language_level=3
# Copyright (c) 2020 Nekokatt
# Copyright (c) 2021-present davfsa
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Application and entities that are used to describe webhooks on Discord."""

from __future__ import annotations

__all__: typing.Sequence[str] = (
    "ApplicationWebhook",
    "ChannelFollowerWebhook",
    "ExecutableWebhook",
    "PartialWebhook",
    "WebhookType",
    "IncomingWebhook",
)

import abc
import typing

import attr

from hikari import channels as channels_
from hikari import snowflakes
from hikari import undefined
from hikari import urls
from hikari.internal import attr_extensions
from hikari.internal import enums
from hikari.internal import routes

if typing.TYPE_CHECKING:
    from hikari import embeds as embeds_
    from hikari import files
    from hikari import files as files_
    from hikari import guilds as guilds_
    from hikari import messages as messages_
    from hikari import traits
    from hikari import users as users_
    from hikari.api import special_endpoints


@typing.final
class WebhookType(int, enums.Enum):
    """Types of webhook."""

    INCOMING = 1
    """Incoming webhook."""

    CHANNEL_FOLLOWER = 2
    """Channel Follower webhook."""

    APPLICATION = 3
    """Application webhook (from the interactions flow)."""


class ExecutableWebhook(abc.ABC):
    """An abstract class with logic for executing entities as webhooks."""

    # This is a mixin, do not add slotted fields.
    __slots__: typing.Sequence[str] = ()

    @property
    @abc.abstractmethod
    def app(self) -> traits.RESTAware:
        """Client application that models may use for procedures."""

    @property
    @abc.abstractmethod
    def webhook_id(self) -> snowflakes.Snowflake:
        """ID used to execute this entity as a webhook."""

    @property
    @abc.abstractmethod
    def token(self) -> typing.Optional[str]:
        """Webhook's token.

        .. note::
            If this is `None` then the methods provided by `ExecutableWebhook`
            will always raise a `ValueError`.
        """

    async def execute(
        self,
        content: undefined.UndefinedOr[typing.Any] = undefined.UNDEFINED,
        *,
        username: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        avatar_url: typing.Union[undefined.UndefinedType, str, files.URL] = undefined.UNDEFINED,
        tts: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        attachment: undefined.UndefinedOr[files_.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files_.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedOr[typing.Sequence[special_endpoints.ComponentBuilder]] = undefined.UNDEFINED,
        embed: undefined.UndefinedOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users_.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds_.PartialRole], bool]
        ] = undefined.UNDEFINED,
        flags: typing.Union[undefined.UndefinedType, int, messages_.MessageFlag] = undefined.UNDEFINED,
    ) -> messages_.Message:
        """Execute the webhook to create a message.

        .. warning::
            At the time of writing, `username` and `avatar_url` are ignored for
            interaction webhooks.

            Additionally, flags this can only be set for interaction webhooks
            and the only settable flag is EPHEMERAL; this field is just
            ignored for non-interaction webhooks.

        Parameters
        ----------
        content : hikari.undefined.UndefinedOr[typing.Any]
            If provided, the message contents. If
            `hikari.undefined.UNDEFINED`, then nothing will be sent
            in the content. Any other value here will be cast to a
            `str`.

            If this is a `hikari.embeds.Embed` and no `embed` kwarg is
            provided, then this will instead update the embed. This allows for
            simpler syntax when sending an embed alone.

            Likewise, if this is a `hikari.files.Resource`, then the
            content is instead treated as an attachment if no `attachment` and
            no `attachments` kwargs are provided.

        Other Parameters
        ----------------
        username : hikari.undefined.UndefinedOr[str]
            If provided, the username to override the webhook's username
            for this request.
        avatar_url : typing.Union[hikari.undefined.UndefinedType, hikari.files.URL, str]
            If provided, the url of an image to override the webhook's
            avatar with for this request.
        tts : hikari.undefined.UndefinedOr[bool]
            If provided, whether the message will be sent as a TTS message.
        attachment : hikari.undefined.UndefinedOr[hikari.files.Resourceish]
            If provided, the message attachment. This can be a resource,
            or string of a path on your computer or a URL.
        attachments : hikari.undefined.UndefinedOr[typing.Sequence[hikari.files.Resourceish]]
            If provided, the message attachments. These can be resources, or
            strings consisting of paths on your computer or URLs.
        component : hikari.undefined.UndefinedOr[hikari.api.special_endpoints.ComponentBuilder]
            If provided, builder object of the component to include in this message.
        components : hikari.undefined.UndefinedOr[typing.Sequence[hikari.api.special_endpoints.ComponentBuilder]]
            If provided, a sequence of the component builder objects to include
            in this message.
        embed : hikari.undefined.UndefinedOr[hikari.embeds.Embed]
            If provided, the message embed.
        embeds : hikari.undefined.UndefinedOr[typing.Sequence[hikari.embeds.Embed]]
            If provided, the message embeds.
        mentions_everyone : hikari.undefined.UndefinedOr[bool]
            If provided, whether the message should parse @everyone/@here
            mentions.
        user_mentions : hikari.undefined.UndefinedOr[typing.Union[hikari.snowflakes.SnowflakeishSequence[hikari.users.PartialUser], bool]]
            If provided, and `True`, all mentions will be parsed.
            If provided, and `False`, no mentions will be parsed.
            Alternatively this may be a collection of
            `hikari.snowflakes.Snowflake`, or
            `hikari.users.PartialUser` derivatives to enforce mentioning
            specific users.
        role_mentions : hikari.undefined.UndefinedOr[typing.Union[hikari.snowflakes.SnowflakeishSequence[hikari.guilds.PartialRole], bool]]
            If provided, and `True`, all mentions will be parsed.
            If provided, and `False`, no mentions will be parsed.
            Alternatively this may be a collection of
            `hikari.snowflakes.Snowflake`, or
            `hikari.guilds.PartialRole` derivatives to enforce mentioning
            specific roles.
        flags : typing.Union[hikari.undefined.UndefinedType, int, hikari.messages.MessageFlag]
            The flags to set for this webhook message.

        Returns
        -------
        hikari.messages.Message
            The created message object.

        Raises
        ------
        hikari.errors.NotFoundError
            If the current webhook is not found.
        hikari.errors.BadRequestError
            This can be raised if the file is too large; if the embed exceeds
            the defined limits; if the message content is specified only and
            empty or greater than `2000` characters; if neither content, file
            or embeds are specified.
            If any invalid snowflake IDs are passed; a snowflake may be invalid
            due to it being outside of the range of a 64 bit integer.
        hikari.errors.UnauthorizedError
            If you pass a token that's invalid for the target webhook.
        ValueError
            If either `ExecutableWebhook.token` is `None` or more than 100 unique
            objects/entities are passed for `role_mentions` or `user_mentions or
            if `token` is not available.
        TypeError
            If both `attachment` and `attachments`, `component` and `components`
            or `embed` and `embeds` are specified.
        """  # noqa: E501 - Line too long
        if not self.token:
            raise ValueError("Cannot send a message using a webhook where we don't know the token")

        return await self.app.rest.execute_webhook(
            webhook=self.webhook_id,
            token=self.token,
            content=content,
            username=username,
            avatar_url=avatar_url,
            tts=tts,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            mentions_everyone=mentions_everyone,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
            flags=flags,
        )

    async def fetch_message(self, message: snowflakes.SnowflakeishOr[messages_.Message]) -> messages_.Message:
        """Fetch an old message sent by the webhook.

        Parameters
        ----------
        message : hikari.snowflakes.SnowflakeishOr[hikari.messages.PartialMessage]
            The message to fetch. This may be the object or the ID of an
            existing channel.

        Returns
        -------
        hikari.messages.Message
            The requested message.

        Raises
        ------
        ValueError
            If `token` is not available.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If the webhook is not found or the webhook's message wasn't found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        if self.token is None:
            raise ValueError("Cannot fetch a message using a webhook where we don't know the token")

        return await self.app.rest.fetch_webhook_message(self.webhook_id, token=self.token, message=message)

    async def edit_message(
        self,
        message: snowflakes.SnowflakeishOr[messages_.Message],
        content: undefined.UndefinedNoneOr[typing.Any] = undefined.UNDEFINED,
        *,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedNoneOr[
            typing.Sequence[special_endpoints.ComponentBuilder]
        ] = undefined.UNDEFINED,
        embed: undefined.UndefinedNoneOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedNoneOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        replace_attachments: bool = False,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users_.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds_.PartialRole], bool]
        ] = undefined.UNDEFINED,
    ) -> messages_.Message:
        """Edit a message sent by a webhook.

        .. note::
            Mentioning everyone, roles, or users in message edits currently
            will not send a push notification showing a new mention to people
            on Discord. It will still highlight in their chat as if they
            were mentioned, however.

        .. warning::
            If you specify a text `content`, `mentions_everyone`,
            `mentions_reply`, `user_mentions`, and `role_mentions` will default
            to `False` as the message will be re-parsed for mentions. This will
            also occur if only one of the four are specified

            This is a limitation of Discord's design. If in doubt, specify all
            four of them each time.

        Parameters
        ----------
        message : hikari.snowflakes.SnowflakeishOr[hikari.messages.PartialMessage]
            The message to delete. This may be the object or the ID of
            an existing message.
        content : hikari.undefined.UndefinedNoneOr[typing.Any]
            If provided, the message contents. If
            `hikari.undefined.UNDEFINED`, then nothing will be sent
            in the content. Any other value here will be cast to a
            `str`.

            If this is a `hikari.embeds.Embed` and no `embed` nor
            no `embeds` kwarg is provided, then this will instead
            update the embed. This allows for simpler syntax when
            sending an embed alone.

            Likewise, if this is a `hikari.files.Resource`, then the
            content is instead treated as an attachment if no `attachment` and
            no `attachments` kwargs are provided.

        Other Parameters
        ----------------
        attachment : hikari.undefined.UndefinedOr[hikari.files.Resourceish]
            If provided, the attachment to set on the message. If
            `hikari.undefined.UNDEFINED`, the previous attachment, if
            present, is not changed. If this is `None`, then the
            attachment is removed, if present. Otherwise, the new attachment
            that was provided will be attached.
        attachments : hikari.undefined.UndefinedOr[typing.Sequence[hikari.files.Resourceish]]
            If provided, the attachments to set on the message. If
            `hikari.undefined.UNDEFINED`, the previous attachments, if
            present, are not changed. If this is `None`, then the
            attachments is removed, if present. Otherwise, the new attachments
            that were provided will be attached.
        component : hikari.undefined.UndefinedNoneOr[hikari.api.special_endpoints.ComponentBuilder]
            If provided, builder object of the component to set for this message.
            This component will replace any previously set components and passing
            `None` will remove all components.
        components : hikari.undefined.UndefinedNoneOr[typing.Sequence[hikari.api.special_endpoints.ComponentBuilder]]
            If provided, a sequence of the component builder objects set for
            this message. These components will replace any previously set
            components and passing `None` or an empty sequence will
            remove all components.
        embed : hikari.undefined.UndefinedNoneOr[hikari.embeds.Embed]
            If provided, the embed to set on the message. If
            `hikari.undefined.UNDEFINED`, the previous embed(s) are not changed.
            If this is `None` then any present embeds are removed.
            Otherwise, the new embed that was provided will be used as the
            replacement.
        embeds : hikari.undefined.UndefinedNoneOr[typing.Sequence[hikari.embeds.Embed]]
            If provided, the embeds to set on the message. If
            `hikari.undefined.UNDEFINED`, the previous embed(s) are not changed.
            If this is `None` then any present embeds are removed.
            Otherwise, the new embeds that were provided will be used as the
            replacement.
        replace_attachments: bool
            Whether to replace the attachments with the provided ones. Defaults
            to `False`.

            Note this will also overwrite the embed attachments.
        mentions_everyone : hikari.undefined.UndefinedOr[bool]
            If provided, sanitation for `@everyone` mentions. If
            `hikari.undefined.UNDEFINED`, then the previous setting is
            not changed. If `True`, then `@everyone`/`@here` mentions
            in the message content will show up as mentioning everyone that can
            view the chat.
        user_mentions : hikari.undefined.UndefinedOr[typing.Union[hikari.snowflakes.SnowflakeishSequence[hikari.users.PartialUser], bool]]
            If provided, and `True`, all user mentions will be detected.
            If provided, and `False`, all user mentions will be ignored
            if appearing in the message body.
            Alternatively this may be a collection of
            `hikari.snowflakes.Snowflake`, or
            `hikari.users.PartialUser` derivatives to enforce mentioning
            specific users.
        role_mentions : hikari.undefined.UndefinedOr[typing.Union[hikari.snowflakes.SnowflakeishSequence[hikari.guilds.PartialRole], bool]]
            If provided, and `True`, all role mentions will be detected.
            If provided, and `False`, all role mentions will be ignored
            if appearing in the message body.
            Alternatively this may be a collection of
            `hikari.snowflakes.Snowflake`, or
            `hikari.guilds.PartialRole` derivatives to enforce mentioning
            specific roles.

        Returns
        -------
        hikari.messages.Message
            The edited message.

        Raises
        ------
        ValueError
            If more than 100 unique objects/entities are passed for
            `role_mentions` or `user_mentions` or `token` is not available.
        TypeError
            If both `attachment` and `attachments` are specified or if both
            `embed` and `embeds` are specified.
        hikari.errors.BadRequestError
            This may be raised in several discrete situations, such as messages
            being empty with no attachments or embeds; messages with more than
            2000 characters in them, embeds that exceed one of the many embed
            limits; too many attachments; attachments that are too large;
            too many components.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If the webhook or the message are not found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """  # noqa: E501 - Line too long
        if self.token is None:
            raise ValueError("Cannot edit a message using a webhook where we don't know the token")

        return await self.app.rest.edit_webhook_message(
            self.webhook_id,
            token=self.token,
            message=message,
            content=content,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            replace_attachments=replace_attachments,
            mentions_everyone=mentions_everyone,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
        )

    async def delete_message(self, message: snowflakes.SnowflakeishOr[messages_.Message]) -> None:
        """Delete a given message in a given channel.

        Parameters
        ----------
        message : hikari.snowflakes.SnowflakeishOr[hikari.messages.PartialMessage]
            The message to delete. This may be the object or the ID of
            an existing message.

        Raises
        ------
        ValueError
            If `token` is not available.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If the webhook or the message are not found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        if self.token is None:
            raise ValueError("Cannot delete a message using a webhook where we don't know the token")

        await self.app.rest.delete_webhook_message(self.webhook_id, token=self.token, message=message)


@attr_extensions.with_copy
@attr.define(hash=True, kw_only=True, weakref_slot=False)
class PartialWebhook(snowflakes.Unique):
    """Base class for all webhook implementations."""

    app: traits.RESTAware = attr.field(
        repr=False, eq=False, hash=False, metadata={attr_extensions.SKIP_DEEP_COPY: True}
    )
    """The client application that models may use for procedures."""

    id: snowflakes.Snowflake = attr.field(hash=True, repr=True)
    """The ID of this entity."""

    type: typing.Union[WebhookType, int] = attr.field(eq=False, hash=False, repr=True)
    """The type of the webhook."""

    name: str = attr.field(eq=False, hash=False, repr=True)
    """The name of the webhook."""

    avatar_hash: typing.Optional[str] = attr.field(eq=False, hash=False, repr=False)
    """The avatar hash of the webhook."""

    application_id: typing.Optional[snowflakes.Snowflake] = attr.field(eq=False, hash=False, repr=False)
    """The ID of the application that created this webhook."""

    def __str__(self) -> str:
        return self.name if self.name is not None else f"Unnamed webhook ID {self.id}"

    @property
    def mention(self) -> str:
        """Return a raw mention string for the given webhook's user.

        .. note::
            This exists purely for consistency. Webhooks do not receive events
            from the gateway, and without some bot backend to support it, will
            not be able to detect mentions of their webhook.

        Example
        -------
        ```py
        >>> some_webhook.mention
        '<@123456789123456789>'
        ```
        """
        return f"<@{self.id}>"

    @property
    def avatar_url(self) -> typing.Optional[files_.URL]:
        """URL for this webhook's avatar, if set.

        May be `None` if no avatar is set. In this case, you should use
        `default_avatar_url` instead.
        """
        return self.make_avatar_url()

    @property
    def default_avatar_url(self) -> files_.URL:
        """Default avatar URL for the user."""  # noqa: D401 - Imperative mood
        return routes.CDN_DEFAULT_USER_AVATAR.compile_to_file(
            urls.CDN_URL,
            discriminator=0,
            file_format="png",
        )

    def make_avatar_url(self, ext: str = "png", size: int = 4096) -> typing.Optional[files_.URL]:
        """Generate the avatar URL for this webhook's custom avatar if set.

        If no avatar is specified, return `None`. In this case, you should
        use `default_avatar` instead.

        Parameters
        ----------
        ext : str
            The extension to use for this URL, defaults to `png`.
            Supports `png`, `jpeg`, `jpg` and `webp`.
        size : int
            The size to set for the URL, defaults to `4096`.
            Can be any power of two between 16 and 4096.
            Will be ignored for default avatars.

        Returns
        -------
        typing.Optional[hikari.files.URL]
            The URL of the resource. `None` if no avatar is set (in
            this case, use the `default_avatar` instead).

        Raises
        ------
        ValueError
            If `size` is not a power of two between 16 and 4096 (inclusive).
        """
        if self.avatar_hash is None:
            return None

        return routes.CDN_USER_AVATAR.compile_to_file(
            urls.CDN_URL,
            user_id=self.id,
            hash=self.avatar_hash,
            size=size,
            file_format=ext,
        )


@attr.define(hash=True, kw_only=True, weakref_slot=False)
class IncomingWebhook(PartialWebhook, ExecutableWebhook):
    """Represents an incoming webhook object on Discord.

    This is an endpoint that can have messages sent to it using standard
    HTTP requests, which enables external services that are not bots to
    send informational messages to specific channels.
    """

    channel_id: snowflakes.Snowflake = attr.field(eq=False, hash=False, repr=True)
    """The channel ID this webhook is for."""

    guild_id: snowflakes.Snowflake = attr.field(eq=False, hash=False, repr=True)
    """The guild ID of the webhook."""

    author: typing.Optional[users_.User] = attr.field(eq=False, hash=False, repr=True)
    """The user that created the webhook

    .. note::
        This will be `None` when fetched with the webhook's token
        rather than bot authorization or when received within audit logs.
    """

    token: typing.Optional[str] = attr.field(eq=False, hash=False, repr=False)
    """The token for the webhook.

    .. note::
        This is only available for incoming webhooks that are created in the
        channel settings.
    """

    @property
    def webhook_id(self) -> snowflakes.Snowflake:
        # <<inherited docstring from ExecutableWebhook>>.
        return self.id

    async def delete(self, *, use_token: undefined.UndefinedOr[bool] = undefined.UNDEFINED) -> None:
        """Delete this webhook.

        Other Parameters
        ----------------
        use_token : hikari.undefined.UndefinedOr[bool]
            If set to `True` then the webhook's token will be used for
            this request; if set to `False` then bot authorization will
            be used; if not specified then the webhook's token will be used for
            the request if it's set else bot authorization.

        Raises
        ------
        hikari.errors.NotFoundError
            If this webhook is not found.
        hikari.errors.ForbiddenError
            If you either lack the `MANAGE_WEBHOOKS` permission or
            are not a member of the guild this webhook belongs to.
        ValueError
            If `use_token` is passed as `True` when `IncomingWebhook.token` is
            `None`.
        """
        token: undefined.UndefinedOr[str] = undefined.UNDEFINED
        if use_token:
            if self.token is None:
                raise ValueError("This webhook's token is unknown, so cannot be used")
            token = self.token

        elif use_token is undefined.UNDEFINED and self.token:
            token = self.token

        await self.app.rest.delete_webhook(self.id, token=token)

    async def edit(
        self,
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        avatar: undefined.UndefinedNoneOr[files_.Resource[files_.AsyncReader]] = undefined.UNDEFINED,
        channel: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.WebhookChannelT]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        use_token: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> IncomingWebhook:
        """Edit this webhook.

        Other Parameters
        ----------------
        name : hikari.undefined.UndefinedOr[str]
            If provided, the new name string.
        avatar : hikari.undefined.UndefinedOr[hikari.files.Resourceish]
            If provided, the new avatar image. If `None`, then
            it is removed. If not specified, nothing is changed.
        channel : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishOr[hikari.channels.WebhookChannelT]]
            If provided, the object or ID of the new channel the given
            webhook should be moved to.
        reason : hikari.undefined.UndefinedOr[str]
            If provided, the audit log reason explaining why the operation
            was performed. This field will be used when using the webhook's
            token rather than bot authorization.
        use_token : hikari.undefined.UndefinedOr[bool]
            If set to `True` then the webhook's token will be used for
            this request; if set to `False` then bot authorization will
            be used; if not specified then the webhook's token will be used for
            the request if it's set else bot authorization.

        Returns
        -------
        IncomingWebhook
            The updated webhook object.

        Raises
        ------
        ValueError
            If `use_token` is passed as `True` when `IncomingWebhook.token` is `None`.
        hikari.errors.BadRequestError
            If any invalid snowflake IDs are passed; a snowflake may be invalid
            due to it being outside of the range of a 64 bit integer.
        hikari.errors.NotFoundError
            If either the webhook or the channel are not found.
        hikari.errors.ForbiddenError
            If you either lack the `MANAGE_WEBHOOKS` permission or
            are not a member of the guild this webhook belongs to.
        hikari.errors.UnauthorizedError
            If you pass a token that's invalid for the target webhook.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        token: undefined.UndefinedOr[str] = undefined.UNDEFINED
        if use_token:
            if self.token is None:
                raise ValueError("This webhook's token is unknown, so cannot be used")
            token = self.token

        elif use_token is undefined.UNDEFINED and self.token:
            token = self.token

        webhook = await self.app.rest.edit_webhook(
            self.id,
            token=token,
            name=name,
            avatar=avatar,
            channel=channel,
            reason=reason,
        )
        assert isinstance(webhook, IncomingWebhook)
        return webhook

    async def fetch_channel(self) -> channels_.WebhookChannelT:
        """Fetch the channel this webhook is for.

        Returns
        -------
        hikari.channels.WebhookChannelT
            The object of the channel this webhook targets.

        Raises
        ------
        hikari.errors.ForbiddenError
            If you don't have access to the channel this webhook belongs to.
        hikari.errors.NotFoundError
            If the channel this message was created in does not exist.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        channel = await self.app.rest.fetch_channel(self.channel_id)
        assert isinstance(channel, channels_.WebhookChannelTypes)
        return channel

    async def fetch_self(self, *, use_token: undefined.UndefinedOr[bool] = undefined.UNDEFINED) -> IncomingWebhook:
        """Fetch this webhook.

        Other Parameters
        ----------------
        use_token : hikari.undefined.UndefinedOr[bool]
            If set to `True` then the webhook's token will be used for
            this request; if set to `False` then bot authorization will
            be used; if not specified then the webhook's token will be used for
            the request if it's set else bot authorization.

        Returns
        -------
        IncomingWebhook
            The requested webhook object.

        Raises
        ------
        ValueError
            If `use_token` is passed as `True` when `Webhook.token`
            is `None`.
        hikari.errors.ForbiddenError
            If you're not in the guild that owns this webhook or
            lack the `MANAGE_WEBHOOKS` permission.
        hikari.errors.NotFoundError
            If the webhook is not found.
        hikari.errors.UnauthorizedError
            If you pass a token that's invalid for the target webhook.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        token: undefined.UndefinedOr[str] = undefined.UNDEFINED
        if use_token:
            if self.token is None:
                raise ValueError("This webhook's token is unknown, so cannot be used")
            token = self.token

        elif use_token is undefined.UNDEFINED and self.token:
            token = self.token

        webhook = await self.app.rest.fetch_webhook(self.id, token=token)
        assert isinstance(webhook, IncomingWebhook)
        return webhook


@attr.define(hash=True, kw_only=True, weakref_slot=False)
class ChannelFollowerWebhook(PartialWebhook):
    """Represents a channel follower webhook object on Discord."""

    channel_id: snowflakes.Snowflake = attr.field(eq=False, hash=False, repr=True)
    """The channel ID this webhook is for."""

    guild_id: snowflakes.Snowflake = attr.field(eq=False, hash=False, repr=True)
    """The guild ID of the webhook."""

    author: typing.Optional[users_.User] = attr.field(eq=False, hash=False, repr=True)
    """The user that created the webhook

    .. note::
        This will be `None` when received within an audit log.
    """

    source_channel: channels_.PartialChannel = attr.field(eq=False, hash=False, repr=True)
    """The partial object of the channel this webhook is following."""

    source_guild: guilds_.PartialGuild = attr.field(eq=False, hash=False, repr=True)
    """The partial object of the guild this webhook is following."""

    async def delete(self) -> None:
        """Delete this webhook.

        Raises
        ------
        hikari.errors.NotFoundError
            If this webhook is not found.
        hikari.errors.ForbiddenError
            If you either lack the `MANAGE_WEBHOOKS` permission or
            are not a member of the guild this webhook belongs to.
        """
        await self.app.rest.delete_webhook(self.id)

    async def edit(
        self,
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        avatar: undefined.UndefinedNoneOr[files_.Resource[files_.AsyncReader]] = undefined.UNDEFINED,
        channel: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.WebhookChannelT]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> ChannelFollowerWebhook:
        """Edit this webhook.

        Other Parameters
        ----------------
        name : hikari.undefined.UndefinedOr[str]
            If provided, the new name string.
        avatar : hikari.undefined.UndefinedOr[hikari.files.Resourceish]
            If provided, the new avatar image. If `None`, then
            it is removed. If not specified, nothing is changed.
        channel : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishOr[hikari.channels.WebhookChannelT]]
            If provided, the object or ID of the new channel the given
            webhook should be moved to.
        reason : hikari.undefined.UndefinedOr[str]
            If provided, the audit log reason explaining why the operation
            was performed. This field will be used when using the webhook's
            token rather than bot authorization.

        Returns
        -------
        hikari.webhooks.ChannelFollowerWebhook
            The updated webhook object.

        Raises
        ------
        hikari.errors.BadRequestError
            If any invalid snowflake IDs are passed; a snowflake may be invalid
            due to it being outside of the range of a 64 bit integer.
        hikari.errors.NotFoundError
            If either the webhook or the channel are not found.
        hikari.errors.ForbiddenError
            If you either lack the `MANAGE_WEBHOOKS` permission or
            are not a member of the guild this webhook belongs to.
        hikari.errors.UnauthorizedError
            If you pass a token that's invalid for the target webhook.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        webhook = await self.app.rest.edit_webhook(
            self.id,
            name=name,
            avatar=avatar,
            channel=channel,
            reason=reason,
        )
        assert isinstance(webhook, ChannelFollowerWebhook)
        return webhook

    async def fetch_channel(self) -> channels_.WebhookChannelT:
        """Fetch the channel this webhook is for.

        Returns
        -------
        hikari.channels.WebhookChannelT
            The object of the channel this webhook targets.

        Raises
        ------
        hikari.errors.ForbiddenError
            If you don't have access to the channel this webhook belongs to.
        hikari.errors.NotFoundError
            If the channel this message was created in does not exist.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        channel = await self.app.rest.fetch_channel(self.channel_id)
        assert isinstance(channel, channels_.WebhookChannelTypes)
        return channel

    async def fetch_self(self) -> ChannelFollowerWebhook:
        """Fetch this webhook.

        Returns
        -------
        hikari.webhooks.ChannelFollowerWebhook
            The requested webhook object.

        Raises
        ------
        hikari.errors.ForbiddenError
            If you're not in the guild that owns this webhook or
            lack the `MANAGE_WEBHOOKS` permission.
        hikari.errors.NotFoundError
            If the webhook is not found.
        hikari.errors.UnauthorizedError
            If you pass a token that's invalid for the target webhook.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        webhook = await self.app.rest.fetch_webhook(self.id)
        assert isinstance(webhook, ChannelFollowerWebhook)
        return webhook


@attr.define(hash=True, kw_only=True, weakref_slot=False)
class ApplicationWebhook(PartialWebhook):
    """Represents an application webhook object on Discord.

    This is from the interactions flow.
    """

    application_id: snowflakes.Snowflake = attr.ib()
    # <<inherited docstring from PartialWebhook>>.
#  
@attr.define(hash=True, kw_only=True, weakref_slot=False)
class ApplicationWebhook(PartialWebhook):
View Source
@attr.define(hash=True, kw_only=True, weakref_slot=False)
class ApplicationWebhook(PartialWebhook):
    """Represents an application webhook object on Discord.

    This is from the interactions flow.
    """

    application_id: snowflakes.Snowflake = attr.ib()
    # <<inherited docstring from PartialWebhook>>.

Represents an application webhook object on Discord.

This is from the interactions flow.

Variables and properties

The client application that models may use for procedures.

The ID of the application that created this webhook.

#  avatar_hash: Optional[str]

The avatar hash of the webhook.

#  avatar_url: Optional[hikari.files.URL]

URL for this webhook's avatar, if set.

May be None if no avatar is set. In this case, you should use default_avatar_url instead.

#  created_at: datetime.datetime

When the object was created.

#  default_avatar_url: hikari.files.URL

Default avatar URL for the user.

The ID of this entity.

#  mention: str

Return a raw mention string for the given webhook's user.

Note: This exists purely for consistency. Webhooks do not receive events from the gateway, and without some bot backend to support it, will not be able to detect mentions of their webhook.

Example
>>> some_webhook.mention
'<@123456789123456789>'
#  name: str

The name of the webhook.

The type of the webhook.

Methods
#  def __init__(
   self,
   *,
   app: hikari.traits.RESTAware,
   id: hikari.snowflakes.Snowflake,
   type: Union[hikari.webhooks.WebhookType, int],
   name: str,
   avatar_hash: Optional[str],
   application_id: hikari.snowflakes.Snowflake
):
View Source
def __init__(self, *, app, id, type, name, avatar_hash, application_id):
    self.app = app
    self.id = id
    self.type = type
    self.name = name
    self.avatar_hash = avatar_hash
    self.application_id = application_id

Method generated by attrs for class ApplicationWebhook.

#  def make_avatar_url(
   self,
   ext: str = 'png',
   size: int = 4096
) -> Optional[hikari.files.URL]:
View Source
    def make_avatar_url(self, ext: str = "png", size: int = 4096) -> typing.Optional[files_.URL]:
        """Generate the avatar URL for this webhook's custom avatar if set.

        If no avatar is specified, return `None`. In this case, you should
        use `default_avatar` instead.

        Parameters
        ----------
        ext : str
            The extension to use for this URL, defaults to `png`.
            Supports `png`, `jpeg`, `jpg` and `webp`.
        size : int
            The size to set for the URL, defaults to `4096`.
            Can be any power of two between 16 and 4096.
            Will be ignored for default avatars.

        Returns
        -------
        typing.Optional[hikari.files.URL]
            The URL of the resource. `None` if no avatar is set (in
            this case, use the `default_avatar` instead).

        Raises
        ------
        ValueError
            If `size` is not a power of two between 16 and 4096 (inclusive).
        """
        if self.avatar_hash is None:
            return None

        return routes.CDN_USER_AVATAR.compile_to_file(
            urls.CDN_URL,
            user_id=self.id,
            hash=self.avatar_hash,
            size=size,
            file_format=ext,
        )

Generate the avatar URL for this webhook's custom avatar if set.

If no avatar is specified, return None. In this case, you should use default_avatar instead.

Parameters
  • ext (str): The extension to use for this URL, defaults to png. Supports png, jpeg, jpg and webp.
  • size (int): The size to set for the URL, defaults to 4096. Can be any power of two between 16 and 4096. Will be ignored for default avatars.
Returns
  • typing.Optional[hikari.files.URL]: The URL of the resource. None if no avatar is set (in this case, use the default_avatar instead).
Raises
  • ValueError: If size is not a power of two between 16 and 4096 (inclusive).
#  
@attr.define(hash=True, kw_only=True, weakref_slot=False)
class ChannelFollowerWebhook(PartialWebhook):
View Source
@attr.define(hash=True, kw_only=True, weakref_slot=False)
class ChannelFollowerWebhook(PartialWebhook):
    """Represents a channel follower webhook object on Discord."""

    channel_id: snowflakes.Snowflake = attr.field(eq=False, hash=False, repr=True)
    """The channel ID this webhook is for."""

    guild_id: snowflakes.Snowflake = attr.field(eq=False, hash=False, repr=True)
    """The guild ID of the webhook."""

    author: typing.Optional[users_.User] = attr.field(eq=False, hash=False, repr=True)
    """The user that created the webhook

    .. note::
        This will be `None` when received within an audit log.
    """

    source_channel: channels_.PartialChannel = attr.field(eq=False, hash=False, repr=True)
    """The partial object of the channel this webhook is following."""

    source_guild: guilds_.PartialGuild = attr.field(eq=False, hash=False, repr=True)
    """The partial object of the guild this webhook is following."""

    async def delete(self) -> None:
        """Delete this webhook.

        Raises
        ------
        hikari.errors.NotFoundError
            If this webhook is not found.
        hikari.errors.ForbiddenError
            If you either lack the `MANAGE_WEBHOOKS` permission or
            are not a member of the guild this webhook belongs to.
        """
        await self.app.rest.delete_webhook(self.id)

    async def edit(
        self,
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        avatar: undefined.UndefinedNoneOr[files_.Resource[files_.AsyncReader]] = undefined.UNDEFINED,
        channel: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.WebhookChannelT]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> ChannelFollowerWebhook:
        """Edit this webhook.

        Other Parameters
        ----------------
        name : hikari.undefined.UndefinedOr[str]
            If provided, the new name string.
        avatar : hikari.undefined.UndefinedOr[hikari.files.Resourceish]
            If provided, the new avatar image. If `None`, then
            it is removed. If not specified, nothing is changed.
        channel : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishOr[hikari.channels.WebhookChannelT]]
            If provided, the object or ID of the new channel the given
            webhook should be moved to.
        reason : hikari.undefined.UndefinedOr[str]
            If provided, the audit log reason explaining why the operation
            was performed. This field will be used when using the webhook's
            token rather than bot authorization.

        Returns
        -------
        hikari.webhooks.ChannelFollowerWebhook
            The updated webhook object.

        Raises
        ------
        hikari.errors.BadRequestError
            If any invalid snowflake IDs are passed; a snowflake may be invalid
            due to it being outside of the range of a 64 bit integer.
        hikari.errors.NotFoundError
            If either the webhook or the channel are not found.
        hikari.errors.ForbiddenError
            If you either lack the `MANAGE_WEBHOOKS` permission or
            are not a member of the guild this webhook belongs to.
        hikari.errors.UnauthorizedError
            If you pass a token that's invalid for the target webhook.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        webhook = await self.app.rest.edit_webhook(
            self.id,
            name=name,
            avatar=avatar,
            channel=channel,
            reason=reason,
        )
        assert isinstance(webhook, ChannelFollowerWebhook)
        return webhook

    async def fetch_channel(self) -> channels_.WebhookChannelT:
        """Fetch the channel this webhook is for.

        Returns
        -------
        hikari.channels.WebhookChannelT
            The object of the channel this webhook targets.

        Raises
        ------
        hikari.errors.ForbiddenError
            If you don't have access to the channel this webhook belongs to.
        hikari.errors.NotFoundError
            If the channel this message was created in does not exist.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        channel = await self.app.rest.fetch_channel(self.channel_id)
        assert isinstance(channel, channels_.WebhookChannelTypes)
        return channel

    async def fetch_self(self) -> ChannelFollowerWebhook:
        """Fetch this webhook.

        Returns
        -------
        hikari.webhooks.ChannelFollowerWebhook
            The requested webhook object.

        Raises
        ------
        hikari.errors.ForbiddenError
            If you're not in the guild that owns this webhook or
            lack the `MANAGE_WEBHOOKS` permission.
        hikari.errors.NotFoundError
            If the webhook is not found.
        hikari.errors.UnauthorizedError
            If you pass a token that's invalid for the target webhook.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        webhook = await self.app.rest.fetch_webhook(self.id)
        assert isinstance(webhook, ChannelFollowerWebhook)
        return webhook

Represents a channel follower webhook object on Discord.

Variables and properties

The client application that models may use for procedures.

#  application_id: Optional[hikari.snowflakes.Snowflake]

The ID of the application that created this webhook.

#  author: Optional[hikari.users.User]

The user that created the webhook

Note: This will be None when received within an audit log.

#  avatar_hash: Optional[str]

The avatar hash of the webhook.

#  avatar_url: Optional[hikari.files.URL]

URL for this webhook's avatar, if set.

May be None if no avatar is set. In this case, you should use default_avatar_url instead.

The channel ID this webhook is for.

#  created_at: datetime.datetime

When the object was created.

#  default_avatar_url: hikari.files.URL

Default avatar URL for the user.

The guild ID of the webhook.

The ID of this entity.

#  mention: str

Return a raw mention string for the given webhook's user.

Note: This exists purely for consistency. Webhooks do not receive events from the gateway, and without some bot backend to support it, will not be able to detect mentions of their webhook.

Example
>>> some_webhook.mention
'<@123456789123456789>'
#  name: str

The name of the webhook.

The partial object of the channel this webhook is following.

The partial object of the guild this webhook is following.

The type of the webhook.

Methods
#  def __init__(
   self,
   *,
   app: hikari.traits.RESTAware,
   id: hikari.snowflakes.Snowflake,
   type: Union[hikari.webhooks.WebhookType, int],
   name: str,
   avatar_hash: Optional[str],
   application_id: Optional[hikari.snowflakes.Snowflake],
   channel_id: hikari.snowflakes.Snowflake,
   guild_id: hikari.snowflakes.Snowflake,
   author: Optional[hikari.users.User],
   source_channel: hikari.channels.PartialChannel,
   source_guild: hikari.guilds.PartialGuild
):
View Source
def __init__(self, *, app, id, type, name, avatar_hash, application_id, channel_id, guild_id, author, source_channel, source_guild):
    self.app = app
    self.id = id
    self.type = type
    self.name = name
    self.avatar_hash = avatar_hash
    self.application_id = application_id
    self.channel_id = channel_id
    self.guild_id = guild_id
    self.author = author
    self.source_channel = source_channel
    self.source_guild = source_guild

Method generated by attrs for class ChannelFollowerWebhook.

#  async def delete(self) -> None:
View Source
    async def delete(self) -> None:
        """Delete this webhook.

        Raises
        ------
        hikari.errors.NotFoundError
            If this webhook is not found.
        hikari.errors.ForbiddenError
            If you either lack the `MANAGE_WEBHOOKS` permission or
            are not a member of the guild this webhook belongs to.
        """
        await self.app.rest.delete_webhook(self.id)

Delete this webhook.

Raises
#  async def edit(
   self,
   *,
   name: Union[str, hikari.undefined.UndefinedType] = UNDEFINED,
   avatar: Union[hikari.files.Resource[hikari.files.AsyncReader], hikari.undefined.UndefinedType, NoneType] = UNDEFINED,
   channel: Union[hikari.channels.GuildTextChannel, hikari.channels.GuildNewsChannel, hikari.snowflakes.Snowflake, int, hikari.undefined.UndefinedType] = UNDEFINED,
   reason: Union[str, hikari.undefined.UndefinedType] = UNDEFINED
) -> hikari.webhooks.ChannelFollowerWebhook:
View Source
    async def edit(
        self,
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        avatar: undefined.UndefinedNoneOr[files_.Resource[files_.AsyncReader]] = undefined.UNDEFINED,
        channel: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.WebhookChannelT]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> ChannelFollowerWebhook:
        """Edit this webhook.

        Other Parameters
        ----------------
        name : hikari.undefined.UndefinedOr[str]
            If provided, the new name string.
        avatar : hikari.undefined.UndefinedOr[hikari.files.Resourceish]
            If provided, the new avatar image. If `None`, then
            it is removed. If not specified, nothing is changed.
        channel : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishOr[hikari.channels.WebhookChannelT]]
            If provided, the object or ID of the new channel the given
            webhook should be moved to.
        reason : hikari.undefined.UndefinedOr[str]
            If provided, the audit log reason explaining why the operation
            was performed. This field will be used when using the webhook's
            token rather than bot authorization.

        Returns
        -------
        hikari.webhooks.ChannelFollowerWebhook
            The updated webhook object.

        Raises
        ------
        hikari.errors.BadRequestError
            If any invalid snowflake IDs are passed; a snowflake may be invalid
            due to it being outside of the range of a 64 bit integer.
        hikari.errors.NotFoundError
            If either the webhook or the channel are not found.
        hikari.errors.ForbiddenError
            If you either lack the `MANAGE_WEBHOOKS` permission or
            are not a member of the guild this webhook belongs to.
        hikari.errors.UnauthorizedError
            If you pass a token that's invalid for the target webhook.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        webhook = await self.app.rest.edit_webhook(
            self.id,
            name=name,
            avatar=avatar,
            channel=channel,
            reason=reason,
        )
        assert isinstance(webhook, ChannelFollowerWebhook)
        return webhook

Edit this webhook.

Other Parameters
Returns
Raises
  • hikari.errors.BadRequestError: If any invalid snowflake IDs are passed; a snowflake may be invalid due to it being outside of the range of a 64 bit integer.
  • hikari.errors.NotFoundError: If either the webhook or the channel are not found.
  • hikari.errors.ForbiddenError: If you either lack the MANAGE_WEBHOOKS permission or are not a member of the guild this webhook belongs to.
  • hikari.errors.UnauthorizedError: If you pass a token that's invalid for the target webhook.
  • hikari.errors.RateLimitTooLongError: Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
  • hikari.errors.RateLimitedError: Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
  • hikari.errors.InternalServerError: If an internal error occurs on Discord while handling the request.
#  async def fetch_channel(
   self
) -> Union[hikari.channels.GuildTextChannel, hikari.channels.GuildNewsChannel]:
View Source
    async def fetch_channel(self) -> channels_.WebhookChannelT:
        """Fetch the channel this webhook is for.

        Returns
        -------
        hikari.channels.WebhookChannelT
            The object of the channel this webhook targets.

        Raises
        ------
        hikari.errors.ForbiddenError
            If you don't have access to the channel this webhook belongs to.
        hikari.errors.NotFoundError
            If the channel this message was created in does not exist.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        channel = await self.app.rest.fetch_channel(self.channel_id)
        assert isinstance(channel, channels_.WebhookChannelTypes)
        return channel

Fetch the channel this webhook is for.

Returns
Raises
  • hikari.errors.ForbiddenError: If you don't have access to the channel this webhook belongs to.
  • hikari.errors.NotFoundError: If the channel this message was created in does not exist.
  • hikari.errors.UnauthorizedError: If you are unauthorized to make the request (invalid/missing token).
  • hikari.errors.RateLimitTooLongError: Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
  • hikari.errors.RateLimitedError: Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
  • hikari.errors.InternalServerError: If an internal error occurs on Discord while handling the request.
#  async def fetch_self(self) -> hikari.webhooks.ChannelFollowerWebhook:
View Source
    async def fetch_self(self) -> ChannelFollowerWebhook:
        """Fetch this webhook.

        Returns
        -------
        hikari.webhooks.ChannelFollowerWebhook
            The requested webhook object.

        Raises
        ------
        hikari.errors.ForbiddenError
            If you're not in the guild that owns this webhook or
            lack the `MANAGE_WEBHOOKS` permission.
        hikari.errors.NotFoundError
            If the webhook is not found.
        hikari.errors.UnauthorizedError
            If you pass a token that's invalid for the target webhook.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        webhook = await self.app.rest.fetch_webhook(self.id)
        assert isinstance(webhook, ChannelFollowerWebhook)
        return webhook

Fetch this webhook.

Returns
Raises
  • hikari.errors.ForbiddenError: If you're not in the guild that owns this webhook or lack the MANAGE_WEBHOOKS permission.
  • hikari.errors.NotFoundError: If the webhook is not found.
  • hikari.errors.UnauthorizedError: If you pass a token that's invalid for the target webhook.
  • hikari.errors.RateLimitTooLongError: Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
  • hikari.errors.RateLimitedError: Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
  • hikari.errors.InternalServerError: If an internal error occurs on Discord while handling the request.
#  def make_avatar_url(
   self,
   ext: str = 'png',
   size: int = 4096
) -> Optional[hikari.files.URL]:
View Source
    def make_avatar_url(self, ext: str = "png", size: int = 4096) -> typing.Optional[files_.URL]:
        """Generate the avatar URL for this webhook's custom avatar if set.

        If no avatar is specified, return `None`. In this case, you should
        use `default_avatar` instead.

        Parameters
        ----------
        ext : str
            The extension to use for this URL, defaults to `png`.
            Supports `png`, `jpeg`, `jpg` and `webp`.
        size : int
            The size to set for the URL, defaults to `4096`.
            Can be any power of two between 16 and 4096.
            Will be ignored for default avatars.

        Returns
        -------
        typing.Optional[hikari.files.URL]
            The URL of the resource. `None` if no avatar is set (in
            this case, use the `default_avatar` instead).

        Raises
        ------
        ValueError
            If `size` is not a power of two between 16 and 4096 (inclusive).
        """
        if self.avatar_hash is None:
            return None

        return routes.CDN_USER_AVATAR.compile_to_file(
            urls.CDN_URL,
            user_id=self.id,
            hash=self.avatar_hash,
            size=size,
            file_format=ext,
        )

Generate the avatar URL for this webhook's custom avatar if set.

If no avatar is specified, return None. In this case, you should use default_avatar instead.

Parameters
  • ext (str): The extension to use for this URL, defaults to png. Supports png, jpeg, jpg and webp.
  • size (int): The size to set for the URL, defaults to 4096. Can be any power of two between 16 and 4096. Will be ignored for default avatars.
Returns
  • typing.Optional[hikari.files.URL]: The URL of the resource. None if no avatar is set (in this case, use the default_avatar instead).
Raises
  • ValueError: If size is not a power of two between 16 and 4096 (inclusive).
#  class ExecutableWebhook(abc.ABC):
View Source
class ExecutableWebhook(abc.ABC):
    """An abstract class with logic for executing entities as webhooks."""

    # This is a mixin, do not add slotted fields.
    __slots__: typing.Sequence[str] = ()

    @property
    @abc.abstractmethod
    def app(self) -> traits.RESTAware:
        """Client application that models may use for procedures."""

    @property
    @abc.abstractmethod
    def webhook_id(self) -> snowflakes.Snowflake:
        """ID used to execute this entity as a webhook."""

    @property
    @abc.abstractmethod
    def token(self) -> typing.Optional[str]:
        """Webhook's token.

        .. note::
            If this is `None` then the methods provided by `ExecutableWebhook`
            will always raise a `ValueError`.
        """

    async def execute(
        self,
        content: undefined.UndefinedOr[typing.Any] = undefined.UNDEFINED,
        *,
        username: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        avatar_url: typing.Union[undefined.UndefinedType, str, files.URL] = undefined.UNDEFINED,
        tts: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        attachment: undefined.UndefinedOr[files_.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files_.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedOr[typing.Sequence[special_endpoints.ComponentBuilder]] = undefined.UNDEFINED,
        embed: undefined.UndefinedOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users_.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds_.PartialRole], bool]
        ] = undefined.UNDEFINED,
        flags: typing.Union[undefined.UndefinedType, int, messages_.MessageFlag] = undefined.UNDEFINED,
    ) -> messages_.Message:
        """Execute the webhook to create a message.

        .. warning::
            At the time of writing, `username` and `avatar_url` are ignored for
            interaction webhooks.

            Additionally, flags this can only be set for interaction webhooks
            and the only settable flag is EPHEMERAL; this field is just
            ignored for non-interaction webhooks.

        Parameters
        ----------
        content : hikari.undefined.UndefinedOr[typing.Any]
            If provided, the message contents. If
            `hikari.undefined.UNDEFINED`, then nothing will be sent
            in the content. Any other value here will be cast to a
            `str`.

            If this is a `hikari.embeds.Embed` and no `embed` kwarg is
            provided, then this will instead update the embed. This allows for
            simpler syntax when sending an embed alone.

            Likewise, if this is a `hikari.files.Resource`, then the
            content is instead treated as an attachment if no `attachment` and
            no `attachments` kwargs are provided.

        Other Parameters
        ----------------
        username : hikari.undefined.UndefinedOr[str]
            If provided, the username to override the webhook's username
            for this request.
        avatar_url : typing.Union[hikari.undefined.UndefinedType, hikari.files.URL, str]
            If provided, the url of an image to override the webhook's
            avatar with for this request.
        tts : hikari.undefined.UndefinedOr[bool]
            If provided, whether the message will be sent as a TTS message.
        attachment : hikari.undefined.UndefinedOr[hikari.files.Resourceish]
            If provided, the message attachment. This can be a resource,
            or string of a path on your computer or a URL.
        attachments : hikari.undefined.UndefinedOr[typing.Sequence[hikari.files.Resourceish]]
            If provided, the message attachments. These can be resources, or
            strings consisting of paths on your computer or URLs.
        component : hikari.undefined.UndefinedOr[hikari.api.special_endpoints.ComponentBuilder]
            If provided, builder object of the component to include in this message.
        components : hikari.undefined.UndefinedOr[typing.Sequence[hikari.api.special_endpoints.ComponentBuilder]]
            If provided, a sequence of the component builder objects to include
            in this message.
        embed : hikari.undefined.UndefinedOr[hikari.embeds.Embed]
            If provided, the message embed.
        embeds : hikari.undefined.UndefinedOr[typing.Sequence[hikari.embeds.Embed]]
            If provided, the message embeds.
        mentions_everyone : hikari.undefined.UndefinedOr[bool]
            If provided, whether the message should parse @everyone/@here
            mentions.
        user_mentions : hikari.undefined.UndefinedOr[typing.Union[hikari.snowflakes.SnowflakeishSequence[hikari.users.PartialUser], bool]]
            If provided, and `True`, all mentions will be parsed.
            If provided, and `False`, no mentions will be parsed.
            Alternatively this may be a collection of
            `hikari.snowflakes.Snowflake`, or
            `hikari.users.PartialUser` derivatives to enforce mentioning
            specific users.
        role_mentions : hikari.undefined.UndefinedOr[typing.Union[hikari.snowflakes.SnowflakeishSequence[hikari.guilds.PartialRole], bool]]
            If provided, and `True`, all mentions will be parsed.
            If provided, and `False`, no mentions will be parsed.
            Alternatively this may be a collection of
            `hikari.snowflakes.Snowflake`, or
            `hikari.guilds.PartialRole` derivatives to enforce mentioning
            specific roles.
        flags : typing.Union[hikari.undefined.UndefinedType, int, hikari.messages.MessageFlag]
            The flags to set for this webhook message.

        Returns
        -------
        hikari.messages.Message
            The created message object.

        Raises
        ------
        hikari.errors.NotFoundError
            If the current webhook is not found.
        hikari.errors.BadRequestError
            This can be raised if the file is too large; if the embed exceeds
            the defined limits; if the message content is specified only and
            empty or greater than `2000` characters; if neither content, file
            or embeds are specified.
            If any invalid snowflake IDs are passed; a snowflake may be invalid
            due to it being outside of the range of a 64 bit integer.
        hikari.errors.UnauthorizedError
            If you pass a token that's invalid for the target webhook.
        ValueError
            If either `ExecutableWebhook.token` is `None` or more than 100 unique
            objects/entities are passed for `role_mentions` or `user_mentions or
            if `token` is not available.
        TypeError
            If both `attachment` and `attachments`, `component` and `components`
            or `embed` and `embeds` are specified.
        """  # noqa: E501 - Line too long
        if not self.token:
            raise ValueError("Cannot send a message using a webhook where we don't know the token")

        return await self.app.rest.execute_webhook(
            webhook=self.webhook_id,
            token=self.token,
            content=content,
            username=username,
            avatar_url=avatar_url,
            tts=tts,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            mentions_everyone=mentions_everyone,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
            flags=flags,
        )

    async def fetch_message(self, message: snowflakes.SnowflakeishOr[messages_.Message]) -> messages_.Message:
        """Fetch an old message sent by the webhook.

        Parameters
        ----------
        message : hikari.snowflakes.SnowflakeishOr[hikari.messages.PartialMessage]
            The message to fetch. This may be the object or the ID of an
            existing channel.

        Returns
        -------
        hikari.messages.Message
            The requested message.

        Raises
        ------
        ValueError
            If `token` is not available.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If the webhook is not found or the webhook's message wasn't found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        if self.token is None:
            raise ValueError("Cannot fetch a message using a webhook where we don't know the token")

        return await self.app.rest.fetch_webhook_message(self.webhook_id, token=self.token, message=message)

    async def edit_message(
        self,
        message: snowflakes.SnowflakeishOr[messages_.Message],
        content: undefined.UndefinedNoneOr[typing.Any] = undefined.UNDEFINED,
        *,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedNoneOr[
            typing.Sequence[special_endpoints.ComponentBuilder]
        ] = undefined.UNDEFINED,
        embed: undefined.UndefinedNoneOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedNoneOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        replace_attachments: bool = False,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users_.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds_.PartialRole], bool]
        ] = undefined.UNDEFINED,
    ) -> messages_.Message:
        """Edit a message sent by a webhook.

        .. note::
            Mentioning everyone, roles, or users in message edits currently
            will not send a push notification showing a new mention to people
            on Discord. It will still highlight in their chat as if they
            were mentioned, however.

        .. warning::
            If you specify a text `content`, `mentions_everyone`,
            `mentions_reply`, `user_mentions`, and `role_mentions` will default
            to `False` as the message will be re-parsed for mentions. This will
            also occur if only one of the four are specified

            This is a limitation of Discord's design. If in doubt, specify all
            four of them each time.

        Parameters
        ----------
        message : hikari.snowflakes.SnowflakeishOr[hikari.messages.PartialMessage]
            The message to delete. This may be the object or the ID of
            an existing message.
        content : hikari.undefined.UndefinedNoneOr[typing.Any]
            If provided, the message contents. If
            `hikari.undefined.UNDEFINED`, then nothing will be sent
            in the content. Any other value here will be cast to a
            `str`.

            If this is a `hikari.embeds.Embed` and no `embed` nor
            no `embeds` kwarg is provided, then this will instead
            update the embed. This allows for simpler syntax when
            sending an embed alone.

            Likewise, if this is a `hikari.files.Resource`, then the
            content is instead treated as an attachment if no `attachment` and
            no `attachments` kwargs are provided.

        Other Parameters
        ----------------
        attachment : hikari.undefined.UndefinedOr[hikari.files.Resourceish]
            If provided, the attachment to set on the message. If
            `hikari.undefined.UNDEFINED`, the previous attachment, if
            present, is not changed. If this is `None`, then the
            attachment is removed, if present. Otherwise, the new attachment
            that was provided will be attached.
        attachments : hikari.undefined.UndefinedOr[typing.Sequence[hikari.files.Resourceish]]
            If provided, the attachments to set on the message. If
            `hikari.undefined.UNDEFINED`, the previous attachments, if
            present, are not changed. If this is `None`, then the
            attachments is removed, if present. Otherwise, the new attachments
            that were provided will be attached.
        component : hikari.undefined.UndefinedNoneOr[hikari.api.special_endpoints.ComponentBuilder]
            If provided, builder object of the component to set for this message.
            This component will replace any previously set components and passing
            `None` will remove all components.
        components : hikari.undefined.UndefinedNoneOr[typing.Sequence[hikari.api.special_endpoints.ComponentBuilder]]
            If provided, a sequence of the component builder objects set for
            this message. These components will replace any previously set
            components and passing `None` or an empty sequence will
            remove all components.
        embed : hikari.undefined.UndefinedNoneOr[hikari.embeds.Embed]
            If provided, the embed to set on the message. If
            `hikari.undefined.UNDEFINED`, the previous embed(s) are not changed.
            If this is `None` then any present embeds are removed.
            Otherwise, the new embed that was provided will be used as the
            replacement.
        embeds : hikari.undefined.UndefinedNoneOr[typing.Sequence[hikari.embeds.Embed]]
            If provided, the embeds to set on the message. If
            `hikari.undefined.UNDEFINED`, the previous embed(s) are not changed.
            If this is `None` then any present embeds are removed.
            Otherwise, the new embeds that were provided will be used as the
            replacement.
        replace_attachments: bool
            Whether to replace the attachments with the provided ones. Defaults
            to `False`.

            Note this will also overwrite the embed attachments.
        mentions_everyone : hikari.undefined.UndefinedOr[bool]
            If provided, sanitation for `@everyone` mentions. If
            `hikari.undefined.UNDEFINED`, then the previous setting is
            not changed. If `True`, then `@everyone`/`@here` mentions
            in the message content will show up as mentioning everyone that can
            view the chat.
        user_mentions : hikari.undefined.UndefinedOr[typing.Union[hikari.snowflakes.SnowflakeishSequence[hikari.users.PartialUser], bool]]
            If provided, and `True`, all user mentions will be detected.
            If provided, and `False`, all user mentions will be ignored
            if appearing in the message body.
            Alternatively this may be a collection of
            `hikari.snowflakes.Snowflake`, or
            `hikari.users.PartialUser` derivatives to enforce mentioning
            specific users.
        role_mentions : hikari.undefined.UndefinedOr[typing.Union[hikari.snowflakes.SnowflakeishSequence[hikari.guilds.PartialRole], bool]]
            If provided, and `True`, all role mentions will be detected.
            If provided, and `False`, all role mentions will be ignored
            if appearing in the message body.
            Alternatively this may be a collection of
            `hikari.snowflakes.Snowflake`, or
            `hikari.guilds.PartialRole` derivatives to enforce mentioning
            specific roles.

        Returns
        -------
        hikari.messages.Message
            The edited message.

        Raises
        ------
        ValueError
            If more than 100 unique objects/entities are passed for
            `role_mentions` or `user_mentions` or `token` is not available.
        TypeError
            If both `attachment` and `attachments` are specified or if both
            `embed` and `embeds` are specified.
        hikari.errors.BadRequestError
            This may be raised in several discrete situations, such as messages
            being empty with no attachments or embeds; messages with more than
            2000 characters in them, embeds that exceed one of the many embed
            limits; too many attachments; attachments that are too large;
            too many components.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If the webhook or the message are not found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """  # noqa: E501 - Line too long
        if self.token is None:
            raise ValueError("Cannot edit a message using a webhook where we don't know the token")

        return await self.app.rest.edit_webhook_message(
            self.webhook_id,
            token=self.token,
            message=message,
            content=content,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            replace_attachments=replace_attachments,
            mentions_everyone=mentions_everyone,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
        )

    async def delete_message(self, message: snowflakes.SnowflakeishOr[messages_.Message]) -> None:
        """Delete a given message in a given channel.

        Parameters
        ----------
        message : hikari.snowflakes.SnowflakeishOr[hikari.messages.PartialMessage]
            The message to delete. This may be the object or the ID of
            an existing message.

        Raises
        ------
        ValueError
            If `token` is not available.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If the webhook or the message are not found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        if self.token is None:
            raise ValueError("Cannot delete a message using a webhook where we don't know the token")

        await self.app.rest.delete_webhook_message(self.webhook_id, token=self.token, message=message)

An abstract class with logic for executing entities as webhooks.

Variables and properties

Client application that models may use for procedures.

#  token: Optional[str]

Webhook's token.

Note: If this is None then the methods provided by ExecutableWebhook will always raise a ValueError.

ID used to execute this entity as a webhook.

Methods
#  async def delete_message(
   self,
   message: Union[hikari.messages.Message, hikari.snowflakes.Snowflake, int]
) -> None:
View Source
    async def delete_message(self, message: snowflakes.SnowflakeishOr[messages_.Message]) -> None:
        """Delete a given message in a given channel.

        Parameters
        ----------
        message : hikari.snowflakes.SnowflakeishOr[hikari.messages.PartialMessage]
            The message to delete. This may be the object or the ID of
            an existing message.

        Raises
        ------
        ValueError
            If `token` is not available.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If the webhook or the message are not found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        if self.token is None:
            raise ValueError("Cannot delete a message using a webhook where we don't know the token")

        await self.app.rest.delete_webhook_message(self.webhook_id, token=self.token, message=message)

Delete a given message in a given channel.

Parameters
Raises
  • ValueError: If token is not available.
  • hikari.errors.UnauthorizedError: If you are unauthorized to make the request (invalid/missing token).
  • hikari.errors.NotFoundError: If the webhook or the message are not found.
  • hikari.errors.RateLimitTooLongError: Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
  • hikari.errors.RateLimitedError: Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
  • hikari.errors.InternalServerError: If an internal error occurs on Discord while handling the request.
#  async def edit_message(
   self,
   message: Union[hikari.messages.Message, hikari.snowflakes.Snowflake, int],
   content: Union[Any, hikari.undefined.UndefinedType, NoneType] = UNDEFINED,
   *,
   attachment: Union[hikari.files.Resource[Any], os.PathLike[str], str, bytes, bytearray, memoryview, _io.BytesIO, _io.StringIO, hikari.undefined.UndefinedType] = UNDEFINED,
   attachments: Union[Sequence[Union[hikari.files.Resource[Any], os.PathLike[str], str, bytes, bytearray, memoryview, _io.BytesIO, _io.StringIO]], hikari.undefined.UndefinedType] = UNDEFINED,
   component: Union[hikari.api.special_endpoints.ComponentBuilder, hikari.undefined.UndefinedType, NoneType] = UNDEFINED,
   components: Union[Sequence[hikari.api.special_endpoints.ComponentBuilder], hikari.undefined.UndefinedType, NoneType] = UNDEFINED,
   embed: Union[hikari.embeds.Embed, hikari.undefined.UndefinedType, NoneType] = UNDEFINED,
   embeds: Union[Sequence[hikari.embeds.Embed], hikari.undefined.UndefinedType, NoneType] = UNDEFINED,
   replace_attachments: bool = False,
   mentions_everyone: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED,
   user_mentions: Union[Sequence[Union[hikari.users.PartialUser, hikari.snowflakes.Snowflake, int]], bool, hikari.undefined.UndefinedType] = UNDEFINED,
   role_mentions: Union[Sequence[Union[hikari.guilds.PartialRole, hikari.snowflakes.Snowflake, int]], bool, hikari.undefined.UndefinedType] = UNDEFINED
) -> hikari.messages.Message:
View Source
    async def edit_message(
        self,
        message: snowflakes.SnowflakeishOr[messages_.Message],
        content: undefined.UndefinedNoneOr[typing.Any] = undefined.UNDEFINED,
        *,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedNoneOr[
            typing.Sequence[special_endpoints.ComponentBuilder]
        ] = undefined.UNDEFINED,
        embed: undefined.UndefinedNoneOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedNoneOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        replace_attachments: bool = False,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users_.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds_.PartialRole], bool]
        ] = undefined.UNDEFINED,
    ) -> messages_.Message:
        """Edit a message sent by a webhook.

        .. note::
            Mentioning everyone, roles, or users in message edits currently
            will not send a push notification showing a new mention to people
            on Discord. It will still highlight in their chat as if they
            were mentioned, however.

        .. warning::
            If you specify a text `content`, `mentions_everyone`,
            `mentions_reply`, `user_mentions`, and `role_mentions` will default
            to `False` as the message will be re-parsed for mentions. This will
            also occur if only one of the four are specified

            This is a limitation of Discord's design. If in doubt, specify all
            four of them each time.

        Parameters
        ----------
        message : hikari.snowflakes.SnowflakeishOr[hikari.messages.PartialMessage]
            The message to delete. This may be the object or the ID of
            an existing message.
        content : hikari.undefined.UndefinedNoneOr[typing.Any]
            If provided, the message contents. If
            `hikari.undefined.UNDEFINED`, then nothing will be sent
            in the content. Any other value here will be cast to a
            `str`.

            If this is a `hikari.embeds.Embed` and no `embed` nor
            no `embeds` kwarg is provided, then this will instead
            update the embed. This allows for simpler syntax when
            sending an embed alone.

            Likewise, if this is a `hikari.files.Resource`, then the
            content is instead treated as an attachment if no `attachment` and
            no `attachments` kwargs are provided.

        Other Parameters
        ----------------
        attachment : hikari.undefined.UndefinedOr[hikari.files.Resourceish]
            If provided, the attachment to set on the message. If
            `hikari.undefined.UNDEFINED`, the previous attachment, if
            present, is not changed. If this is `None`, then the
            attachment is removed, if present. Otherwise, the new attachment
            that was provided will be attached.
        attachments : hikari.undefined.UndefinedOr[typing.Sequence[hikari.files.Resourceish]]
            If provided, the attachments to set on the message. If
            `hikari.undefined.UNDEFINED`, the previous attachments, if
            present, are not changed. If this is `None`, then the
            attachments is removed, if present. Otherwise, the new attachments
            that were provided will be attached.
        component : hikari.undefined.UndefinedNoneOr[hikari.api.special_endpoints.ComponentBuilder]
            If provided, builder object of the component to set for this message.
            This component will replace any previously set components and passing
            `None` will remove all components.
        components : hikari.undefined.UndefinedNoneOr[typing.Sequence[hikari.api.special_endpoints.ComponentBuilder]]
            If provided, a sequence of the component builder objects set for
            this message. These components will replace any previously set
            components and passing `None` or an empty sequence will
            remove all components.
        embed : hikari.undefined.UndefinedNoneOr[hikari.embeds.Embed]
            If provided, the embed to set on the message. If
            `hikari.undefined.UNDEFINED`, the previous embed(s) are not changed.
            If this is `None` then any present embeds are removed.
            Otherwise, the new embed that was provided will be used as the
            replacement.
        embeds : hikari.undefined.UndefinedNoneOr[typing.Sequence[hikari.embeds.Embed]]
            If provided, the embeds to set on the message. If
            `hikari.undefined.UNDEFINED`, the previous embed(s) are not changed.
            If this is `None` then any present embeds are removed.
            Otherwise, the new embeds that were provided will be used as the
            replacement.
        replace_attachments: bool
            Whether to replace the attachments with the provided ones. Defaults
            to `False`.

            Note this will also overwrite the embed attachments.
        mentions_everyone : hikari.undefined.UndefinedOr[bool]
            If provided, sanitation for `@everyone` mentions. If
            `hikari.undefined.UNDEFINED`, then the previous setting is
            not changed. If `True`, then `@everyone`/`@here` mentions
            in the message content will show up as mentioning everyone that can
            view the chat.
        user_mentions : hikari.undefined.UndefinedOr[typing.Union[hikari.snowflakes.SnowflakeishSequence[hikari.users.PartialUser], bool]]
            If provided, and `True`, all user mentions will be detected.
            If provided, and `False`, all user mentions will be ignored
            if appearing in the message body.
            Alternatively this may be a collection of
            `hikari.snowflakes.Snowflake`, or
            `hikari.users.PartialUser` derivatives to enforce mentioning
            specific users.
        role_mentions : hikari.undefined.UndefinedOr[typing.Union[hikari.snowflakes.SnowflakeishSequence[hikari.guilds.PartialRole], bool]]
            If provided, and `True`, all role mentions will be detected.
            If provided, and `False`, all role mentions will be ignored
            if appearing in the message body.
            Alternatively this may be a collection of
            `hikari.snowflakes.Snowflake`, or
            `hikari.guilds.PartialRole` derivatives to enforce mentioning
            specific roles.

        Returns
        -------
        hikari.messages.Message
            The edited message.

        Raises
        ------
        ValueError
            If more than 100 unique objects/entities are passed for
            `role_mentions` or `user_mentions` or `token` is not available.
        TypeError
            If both `attachment` and `attachments` are specified or if both
            `embed` and `embeds` are specified.
        hikari.errors.BadRequestError
            This may be raised in several discrete situations, such as messages
            being empty with no attachments or embeds; messages with more than
            2000 characters in them, embeds that exceed one of the many embed
            limits; too many attachments; attachments that are too large;
            too many components.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If the webhook or the message are not found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """  # noqa: E501 - Line too long
        if self.token is None:
            raise ValueError("Cannot edit a message using a webhook where we don't know the token")

        return await self.app.rest.edit_webhook_message(
            self.webhook_id,
            token=self.token,
            message=message,
            content=content,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            replace_attachments=replace_attachments,
            mentions_everyone=mentions_everyone,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
        )

Edit a message sent by a webhook.

Note: Mentioning everyone, roles, or users in message edits currently will not send a push notification showing a new mention to people on Discord. It will still highlight in their chat as if they were mentioned, however.

Warning: If you specify a text content, mentions_everyone, mentions_reply, user_mentions, and role_mentions will default to False as the message will be re-parsed for mentions. This will also occur if only one of the four are specified

This is a limitation of Discord's design. If in doubt, specify all four of them each time.

Parameters
Other Parameters
Returns
Raises
  • ValueError: If more than 100 unique objects/entities are passed for role_mentions or user_mentions or token is not available.
  • TypeError: If both attachment and attachments are specified or if both embed and embeds are specified.
  • hikari.errors.BadRequestError: This may be raised in several discrete situations, such as messages being empty with no attachments or embeds; messages with more than 2000 characters in them, embeds that exceed one of the many embed limits; too many attachments; attachments that are too large; too many components.
  • hikari.errors.UnauthorizedError: If you are unauthorized to make the request (invalid/missing token).
  • hikari.errors.NotFoundError: If the webhook or the message are not found.
  • hikari.errors.RateLimitTooLongError: Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
  • hikari.errors.RateLimitedError: Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
  • hikari.errors.InternalServerError: If an internal error occurs on Discord while handling the request.
#  async def execute(
   self,
   content: Union[Any, hikari.undefined.UndefinedType] = UNDEFINED,
   *,
   username: Union[str, hikari.undefined.UndefinedType] = UNDEFINED,
   avatar_url: Union[hikari.undefined.UndefinedType, str, hikari.files.URL] = UNDEFINED,
   tts: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED,
   attachment: Union[hikari.files.Resource[Any], os.PathLike[str], str, bytes, bytearray, memoryview, _io.BytesIO, _io.StringIO, hikari.undefined.UndefinedType] = UNDEFINED,
   attachments: Union[Sequence[Union[hikari.files.Resource[Any], os.PathLike[str], str, bytes, bytearray, memoryview, _io.BytesIO, _io.StringIO]], hikari.undefined.UndefinedType] = UNDEFINED,
   component: Union[hikari.api.special_endpoints.ComponentBuilder, hikari.undefined.UndefinedType] = UNDEFINED,
   components: Union[Sequence[hikari.api.special_endpoints.ComponentBuilder], hikari.undefined.UndefinedType] = UNDEFINED,
   embed: Union[hikari.embeds.Embed, hikari.undefined.UndefinedType] = UNDEFINED,
   embeds: Union[Sequence[hikari.embeds.Embed], hikari.undefined.UndefinedType] = UNDEFINED,
   mentions_everyone: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED,
   user_mentions: Union[Sequence[Union[hikari.users.PartialUser, hikari.snowflakes.Snowflake, int]], bool, hikari.undefined.UndefinedType] = UNDEFINED,
   role_mentions: Union[Sequence[Union[hikari.guilds.PartialRole, hikari.snowflakes.Snowflake, int]], bool, hikari.undefined.UndefinedType] = UNDEFINED,
   flags: Union[hikari.undefined.UndefinedType, int, hikari.messages.MessageFlag] = UNDEFINED
) -> hikari.messages.Message:
View Source
    async def execute(
        self,
        content: undefined.UndefinedOr[typing.Any] = undefined.UNDEFINED,
        *,
        username: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        avatar_url: typing.Union[undefined.UndefinedType, str, files.URL] = undefined.UNDEFINED,
        tts: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        attachment: undefined.UndefinedOr[files_.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files_.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedOr[typing.Sequence[special_endpoints.ComponentBuilder]] = undefined.UNDEFINED,
        embed: undefined.UndefinedOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users_.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds_.PartialRole], bool]
        ] = undefined.UNDEFINED,
        flags: typing.Union[undefined.UndefinedType, int, messages_.MessageFlag] = undefined.UNDEFINED,
    ) -> messages_.Message:
        """Execute the webhook to create a message.

        .. warning::
            At the time of writing, `username` and `avatar_url` are ignored for
            interaction webhooks.

            Additionally, flags this can only be set for interaction webhooks
            and the only settable flag is EPHEMERAL; this field is just
            ignored for non-interaction webhooks.

        Parameters
        ----------
        content : hikari.undefined.UndefinedOr[typing.Any]
            If provided, the message contents. If
            `hikari.undefined.UNDEFINED`, then nothing will be sent
            in the content. Any other value here will be cast to a
            `str`.

            If this is a `hikari.embeds.Embed` and no `embed` kwarg is
            provided, then this will instead update the embed. This allows for
            simpler syntax when sending an embed alone.

            Likewise, if this is a `hikari.files.Resource`, then the
            content is instead treated as an attachment if no `attachment` and
            no `attachments` kwargs are provided.

        Other Parameters
        ----------------
        username : hikari.undefined.UndefinedOr[str]
            If provided, the username to override the webhook's username
            for this request.
        avatar_url : typing.Union[hikari.undefined.UndefinedType, hikari.files.URL, str]
            If provided, the url of an image to override the webhook's
            avatar with for this request.
        tts : hikari.undefined.UndefinedOr[bool]
            If provided, whether the message will be sent as a TTS message.
        attachment : hikari.undefined.UndefinedOr[hikari.files.Resourceish]
            If provided, the message attachment. This can be a resource,
            or string of a path on your computer or a URL.
        attachments : hikari.undefined.UndefinedOr[typing.Sequence[hikari.files.Resourceish]]
            If provided, the message attachments. These can be resources, or
            strings consisting of paths on your computer or URLs.
        component : hikari.undefined.UndefinedOr[hikari.api.special_endpoints.ComponentBuilder]
            If provided, builder object of the component to include in this message.
        components : hikari.undefined.UndefinedOr[typing.Sequence[hikari.api.special_endpoints.ComponentBuilder]]
            If provided, a sequence of the component builder objects to include
            in this message.
        embed : hikari.undefined.UndefinedOr[hikari.embeds.Embed]
            If provided, the message embed.
        embeds : hikari.undefined.UndefinedOr[typing.Sequence[hikari.embeds.Embed]]
            If provided, the message embeds.
        mentions_everyone : hikari.undefined.UndefinedOr[bool]
            If provided, whether the message should parse @everyone/@here
            mentions.
        user_mentions : hikari.undefined.UndefinedOr[typing.Union[hikari.snowflakes.SnowflakeishSequence[hikari.users.PartialUser], bool]]
            If provided, and `True`, all mentions will be parsed.
            If provided, and `False`, no mentions will be parsed.
            Alternatively this may be a collection of
            `hikari.snowflakes.Snowflake`, or
            `hikari.users.PartialUser` derivatives to enforce mentioning
            specific users.
        role_mentions : hikari.undefined.UndefinedOr[typing.Union[hikari.snowflakes.SnowflakeishSequence[hikari.guilds.PartialRole], bool]]
            If provided, and `True`, all mentions will be parsed.
            If provided, and `False`, no mentions will be parsed.
            Alternatively this may be a collection of
            `hikari.snowflakes.Snowflake`, or
            `hikari.guilds.PartialRole` derivatives to enforce mentioning
            specific roles.
        flags : typing.Union[hikari.undefined.UndefinedType, int, hikari.messages.MessageFlag]
            The flags to set for this webhook message.

        Returns
        -------
        hikari.messages.Message
            The created message object.

        Raises
        ------
        hikari.errors.NotFoundError
            If the current webhook is not found.
        hikari.errors.BadRequestError
            This can be raised if the file is too large; if the embed exceeds
            the defined limits; if the message content is specified only and
            empty or greater than `2000` characters; if neither content, file
            or embeds are specified.
            If any invalid snowflake IDs are passed; a snowflake may be invalid
            due to it being outside of the range of a 64 bit integer.
        hikari.errors.UnauthorizedError
            If you pass a token that's invalid for the target webhook.
        ValueError
            If either `ExecutableWebhook.token` is `None` or more than 100 unique
            objects/entities are passed for `role_mentions` or `user_mentions or
            if `token` is not available.
        TypeError
            If both `attachment` and `attachments`, `component` and `components`
            or `embed` and `embeds` are specified.
        """  # noqa: E501 - Line too long
        if not self.token:
            raise ValueError("Cannot send a message using a webhook where we don't know the token")

        return await self.app.rest.execute_webhook(
            webhook=self.webhook_id,
            token=self.token,
            content=content,
            username=username,
            avatar_url=avatar_url,
            tts=tts,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            mentions_everyone=mentions_everyone,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
            flags=flags,
        )

Execute the webhook to create a message.

Warning: At the time of writing, username and avatar_url are ignored for interaction webhooks.

Additionally, flags this can only be set for interaction webhooks and the only settable flag is EPHEMERAL; this field is just ignored for non-interaction webhooks.

Parameters
  • content (hikari.undefined.UndefinedOr[typing.Any]): If provided, the message contents. If hikari.undefined.UNDEFINED, then nothing will be sent in the content. Any other value here will be cast to a str.

    If this is a hikari.embeds.Embed and no embed kwarg is provided, then this will instead update the embed. This allows for simpler syntax when sending an embed alone.

    Likewise, if this is a hikari.files.Resource, then the content is instead treated as an attachment if no attachment and no attachments kwargs are provided.

Other Parameters
Returns
Raises
  • hikari.errors.NotFoundError: If the current webhook is not found.
  • hikari.errors.BadRequestError: This can be raised if the file is too large; if the embed exceeds the defined limits; if the message content is specified only and empty or greater than 2000 characters; if neither content, file or embeds are specified. If any invalid snowflake IDs are passed; a snowflake may be invalid due to it being outside of the range of a 64 bit integer.
  • hikari.errors.UnauthorizedError: If you pass a token that's invalid for the target webhook.
  • ValueError: If either ExecutableWebhook.token is None or more than 100 unique objects/entities are passed for role_mentions or user_mentions or iftoken` is not available.
  • TypeError: If both attachment and attachments, component and components or embed and embeds are specified.
#  async def fetch_message(
   self,
   message: Union[hikari.messages.Message, hikari.snowflakes.Snowflake, int]
) -> hikari.messages.Message:
View Source
    async def fetch_message(self, message: snowflakes.SnowflakeishOr[messages_.Message]) -> messages_.Message:
        """Fetch an old message sent by the webhook.

        Parameters
        ----------
        message : hikari.snowflakes.SnowflakeishOr[hikari.messages.PartialMessage]
            The message to fetch. This may be the object or the ID of an
            existing channel.

        Returns
        -------
        hikari.messages.Message
            The requested message.

        Raises
        ------
        ValueError
            If `token` is not available.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If the webhook is not found or the webhook's message wasn't found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        if self.token is None:
            raise ValueError("Cannot fetch a message using a webhook where we don't know the token")

        return await self.app.rest.fetch_webhook_message(self.webhook_id, token=self.token, message=message)

Fetch an old message sent by the webhook.

Parameters
Returns
Raises
  • ValueError: If token is not available.
  • hikari.errors.UnauthorizedError: If you are unauthorized to make the request (invalid/missing token).
  • hikari.errors.NotFoundError: If the webhook is not found or the webhook's message wasn't found.
  • hikari.errors.RateLimitTooLongError: Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
  • hikari.errors.RateLimitedError: Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
  • hikari.errors.InternalServerError: If an internal error occurs on Discord while handling the request.
#  
@attr.define(hash=True, kw_only=True, weakref_slot=False)
class IncomingWebhook(PartialWebhook, ExecutableWebhook):
View Source
@attr.define(hash=True, kw_only=True, weakref_slot=False)
class IncomingWebhook(PartialWebhook, ExecutableWebhook):
    """Represents an incoming webhook object on Discord.

    This is an endpoint that can have messages sent to it using standard
    HTTP requests, which enables external services that are not bots to
    send informational messages to specific channels.
    """

    channel_id: snowflakes.Snowflake = attr.field(eq=False, hash=False, repr=True)
    """The channel ID this webhook is for."""

    guild_id: snowflakes.Snowflake = attr.field(eq=False, hash=False, repr=True)
    """The guild ID of the webhook."""

    author: typing.Optional[users_.User] = attr.field(eq=False, hash=False, repr=True)
    """The user that created the webhook

    .. note::
        This will be `None` when fetched with the webhook's token
        rather than bot authorization or when received within audit logs.
    """

    token: typing.Optional[str] = attr.field(eq=False, hash=False, repr=False)
    """The token for the webhook.

    .. note::
        This is only available for incoming webhooks that are created in the
        channel settings.
    """

    @property
    def webhook_id(self) -> snowflakes.Snowflake:
        # <<inherited docstring from ExecutableWebhook>>.
        return self.id

    async def delete(self, *, use_token: undefined.UndefinedOr[bool] = undefined.UNDEFINED) -> None:
        """Delete this webhook.

        Other Parameters
        ----------------
        use_token : hikari.undefined.UndefinedOr[bool]
            If set to `True` then the webhook's token will be used for
            this request; if set to `False` then bot authorization will
            be used; if not specified then the webhook's token will be used for
            the request if it's set else bot authorization.

        Raises
        ------
        hikari.errors.NotFoundError
            If this webhook is not found.
        hikari.errors.ForbiddenError
            If you either lack the `MANAGE_WEBHOOKS` permission or
            are not a member of the guild this webhook belongs to.
        ValueError
            If `use_token` is passed as `True` when `IncomingWebhook.token` is
            `None`.
        """
        token: undefined.UndefinedOr[str] = undefined.UNDEFINED
        if use_token:
            if self.token is None:
                raise ValueError("This webhook's token is unknown, so cannot be used")
            token = self.token

        elif use_token is undefined.UNDEFINED and self.token:
            token = self.token

        await self.app.rest.delete_webhook(self.id, token=token)

    async def edit(
        self,
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        avatar: undefined.UndefinedNoneOr[files_.Resource[files_.AsyncReader]] = undefined.UNDEFINED,
        channel: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.WebhookChannelT]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        use_token: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> IncomingWebhook:
        """Edit this webhook.

        Other Parameters
        ----------------
        name : hikari.undefined.UndefinedOr[str]
            If provided, the new name string.
        avatar : hikari.undefined.UndefinedOr[hikari.files.Resourceish]
            If provided, the new avatar image. If `None`, then
            it is removed. If not specified, nothing is changed.
        channel : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishOr[hikari.channels.WebhookChannelT]]
            If provided, the object or ID of the new channel the given
            webhook should be moved to.
        reason : hikari.undefined.UndefinedOr[str]
            If provided, the audit log reason explaining why the operation
            was performed. This field will be used when using the webhook's
            token rather than bot authorization.
        use_token : hikari.undefined.UndefinedOr[bool]
            If set to `True` then the webhook's token will be used for
            this request; if set to `False` then bot authorization will
            be used; if not specified then the webhook's token will be used for
            the request if it's set else bot authorization.

        Returns
        -------
        IncomingWebhook
            The updated webhook object.

        Raises
        ------
        ValueError
            If `use_token` is passed as `True` when `IncomingWebhook.token` is `None`.
        hikari.errors.BadRequestError
            If any invalid snowflake IDs are passed; a snowflake may be invalid
            due to it being outside of the range of a 64 bit integer.
        hikari.errors.NotFoundError
            If either the webhook or the channel are not found.
        hikari.errors.ForbiddenError
            If you either lack the `MANAGE_WEBHOOKS` permission or
            are not a member of the guild this webhook belongs to.
        hikari.errors.UnauthorizedError
            If you pass a token that's invalid for the target webhook.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        token: undefined.UndefinedOr[str] = undefined.UNDEFINED
        if use_token:
            if self.token is None:
                raise ValueError("This webhook's token is unknown, so cannot be used")
            token = self.token

        elif use_token is undefined.UNDEFINED and self.token:
            token = self.token

        webhook = await self.app.rest.edit_webhook(
            self.id,
            token=token,
            name=name,
            avatar=avatar,
            channel=channel,
            reason=reason,
        )
        assert isinstance(webhook, IncomingWebhook)
        return webhook

    async def fetch_channel(self) -> channels_.WebhookChannelT:
        """Fetch the channel this webhook is for.

        Returns
        -------
        hikari.channels.WebhookChannelT
            The object of the channel this webhook targets.

        Raises
        ------
        hikari.errors.ForbiddenError
            If you don't have access to the channel this webhook belongs to.
        hikari.errors.NotFoundError
            If the channel this message was created in does not exist.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        channel = await self.app.rest.fetch_channel(self.channel_id)
        assert isinstance(channel, channels_.WebhookChannelTypes)
        return channel

    async def fetch_self(self, *, use_token: undefined.UndefinedOr[bool] = undefined.UNDEFINED) -> IncomingWebhook:
        """Fetch this webhook.

        Other Parameters
        ----------------
        use_token : hikari.undefined.UndefinedOr[bool]
            If set to `True` then the webhook's token will be used for
            this request; if set to `False` then bot authorization will
            be used; if not specified then the webhook's token will be used for
            the request if it's set else bot authorization.

        Returns
        -------
        IncomingWebhook
            The requested webhook object.

        Raises
        ------
        ValueError
            If `use_token` is passed as `True` when `Webhook.token`
            is `None`.
        hikari.errors.ForbiddenError
            If you're not in the guild that owns this webhook or
            lack the `MANAGE_WEBHOOKS` permission.
        hikari.errors.NotFoundError
            If the webhook is not found.
        hikari.errors.UnauthorizedError
            If you pass a token that's invalid for the target webhook.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        token: undefined.UndefinedOr[str] = undefined.UNDEFINED
        if use_token:
            if self.token is None:
                raise ValueError("This webhook's token is unknown, so cannot be used")
            token = self.token

        elif use_token is undefined.UNDEFINED and self.token:
            token = self.token

        webhook = await self.app.rest.fetch_webhook(self.id, token=token)
        assert isinstance(webhook, IncomingWebhook)
        return webhook

Represents an incoming webhook object on Discord.

This is an endpoint that can have messages sent to it using standard HTTP requests, which enables external services that are not bots to send informational messages to specific channels.

Variables and properties

The client application that models may use for procedures.

#  application_id: Optional[hikari.snowflakes.Snowflake]

The ID of the application that created this webhook.

#  author: Optional[hikari.users.User]

The user that created the webhook

Note: This will be None when fetched with the webhook's token rather than bot authorization or when received within audit logs.

#  avatar_hash: Optional[str]

The avatar hash of the webhook.

#  avatar_url: Optional[hikari.files.URL]

URL for this webhook's avatar, if set.

May be None if no avatar is set. In this case, you should use default_avatar_url instead.

The channel ID this webhook is for.

#  created_at: datetime.datetime

When the object was created.

#  default_avatar_url: hikari.files.URL

Default avatar URL for the user.

The guild ID of the webhook.

The ID of this entity.

#  mention: str

Return a raw mention string for the given webhook's user.

Note: This exists purely for consistency. Webhooks do not receive events from the gateway, and without some bot backend to support it, will not be able to detect mentions of their webhook.

Example
>>> some_webhook.mention
'<@123456789123456789>'
#  name: str

The name of the webhook.

#  token: Optional[str]

The token for the webhook.

Note: This is only available for incoming webhooks that are created in the channel settings.

The type of the webhook.

ID used to execute this entity as a webhook.

Methods
#  def __init__(
   self,
   *,
   app: hikari.traits.RESTAware,
   id: hikari.snowflakes.Snowflake,
   type: Union[hikari.webhooks.WebhookType, int],
   name: str,
   avatar_hash: Optional[str],
   application_id: Optional[hikari.snowflakes.Snowflake],
   channel_id: hikari.snowflakes.Snowflake,
   guild_id: hikari.snowflakes.Snowflake,
   author: Optional[hikari.users.User],
   token: Optional[str]
):
View Source
def __init__(self, *, app, id, type, name, avatar_hash, application_id, channel_id, guild_id, author, token):
    self.app = app
    self.id = id
    self.type = type
    self.name = name
    self.avatar_hash = avatar_hash
    self.application_id = application_id
    self.channel_id = channel_id
    self.guild_id = guild_id
    self.author = author
    self.token = token

Method generated by attrs for class IncomingWebhook.

#  async def delete(
   self,
   *,
   use_token: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED
) -> None:
View Source
    async def delete(self, *, use_token: undefined.UndefinedOr[bool] = undefined.UNDEFINED) -> None:
        """Delete this webhook.

        Other Parameters
        ----------------
        use_token : hikari.undefined.UndefinedOr[bool]
            If set to `True` then the webhook's token will be used for
            this request; if set to `False` then bot authorization will
            be used; if not specified then the webhook's token will be used for
            the request if it's set else bot authorization.

        Raises
        ------
        hikari.errors.NotFoundError
            If this webhook is not found.
        hikari.errors.ForbiddenError
            If you either lack the `MANAGE_WEBHOOKS` permission or
            are not a member of the guild this webhook belongs to.
        ValueError
            If `use_token` is passed as `True` when `IncomingWebhook.token` is
            `None`.
        """
        token: undefined.UndefinedOr[str] = undefined.UNDEFINED
        if use_token:
            if self.token is None:
                raise ValueError("This webhook's token is unknown, so cannot be used")
            token = self.token

        elif use_token is undefined.UNDEFINED and self.token:
            token = self.token

        await self.app.rest.delete_webhook(self.id, token=token)

Delete this webhook.

Other Parameters
  • use_token (hikari.undefined.UndefinedOr[bool]): If set to True then the webhook's token will be used for this request; if set to False then bot authorization will be used; if not specified then the webhook's token will be used for the request if it's set else bot authorization.
Raises
#  async def delete_message(
   self,
   message: Union[hikari.messages.Message, hikari.snowflakes.Snowflake, int]
) -> None:
View Source
    async def delete_message(self, message: snowflakes.SnowflakeishOr[messages_.Message]) -> None:
        """Delete a given message in a given channel.

        Parameters
        ----------
        message : hikari.snowflakes.SnowflakeishOr[hikari.messages.PartialMessage]
            The message to delete. This may be the object or the ID of
            an existing message.

        Raises
        ------
        ValueError
            If `token` is not available.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If the webhook or the message are not found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        if self.token is None:
            raise ValueError("Cannot delete a message using a webhook where we don't know the token")

        await self.app.rest.delete_webhook_message(self.webhook_id, token=self.token, message=message)

Delete a given message in a given channel.

Parameters
Raises
  • ValueError: If token is not available.
  • hikari.errors.UnauthorizedError: If you are unauthorized to make the request (invalid/missing token).
  • hikari.errors.NotFoundError: If the webhook or the message are not found.
  • hikari.errors.RateLimitTooLongError: Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
  • hikari.errors.RateLimitedError: Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
  • hikari.errors.InternalServerError: If an internal error occurs on Discord while handling the request.
#  async def edit(
   self,
   *,
   name: Union[str, hikari.undefined.UndefinedType] = UNDEFINED,
   avatar: Union[hikari.files.Resource[hikari.files.AsyncReader], hikari.undefined.UndefinedType, NoneType] = UNDEFINED,
   channel: Union[hikari.channels.GuildTextChannel, hikari.channels.GuildNewsChannel, hikari.snowflakes.Snowflake, int, hikari.undefined.UndefinedType] = UNDEFINED,
   reason: Union[str, hikari.undefined.UndefinedType] = UNDEFINED,
   use_token: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED
) -> hikari.webhooks.IncomingWebhook:
View Source
    async def edit(
        self,
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        avatar: undefined.UndefinedNoneOr[files_.Resource[files_.AsyncReader]] = undefined.UNDEFINED,
        channel: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.WebhookChannelT]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        use_token: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> IncomingWebhook:
        """Edit this webhook.

        Other Parameters
        ----------------
        name : hikari.undefined.UndefinedOr[str]
            If provided, the new name string.
        avatar : hikari.undefined.UndefinedOr[hikari.files.Resourceish]
            If provided, the new avatar image. If `None`, then
            it is removed. If not specified, nothing is changed.
        channel : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishOr[hikari.channels.WebhookChannelT]]
            If provided, the object or ID of the new channel the given
            webhook should be moved to.
        reason : hikari.undefined.UndefinedOr[str]
            If provided, the audit log reason explaining why the operation
            was performed. This field will be used when using the webhook's
            token rather than bot authorization.
        use_token : hikari.undefined.UndefinedOr[bool]
            If set to `True` then the webhook's token will be used for
            this request; if set to `False` then bot authorization will
            be used; if not specified then the webhook's token will be used for
            the request if it's set else bot authorization.

        Returns
        -------
        IncomingWebhook
            The updated webhook object.

        Raises
        ------
        ValueError
            If `use_token` is passed as `True` when `IncomingWebhook.token` is `None`.
        hikari.errors.BadRequestError
            If any invalid snowflake IDs are passed; a snowflake may be invalid
            due to it being outside of the range of a 64 bit integer.
        hikari.errors.NotFoundError
            If either the webhook or the channel are not found.
        hikari.errors.ForbiddenError
            If you either lack the `MANAGE_WEBHOOKS` permission or
            are not a member of the guild this webhook belongs to.
        hikari.errors.UnauthorizedError
            If you pass a token that's invalid for the target webhook.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        token: undefined.UndefinedOr[str] = undefined.UNDEFINED
        if use_token:
            if self.token is None:
                raise ValueError("This webhook's token is unknown, so cannot be used")
            token = self.token

        elif use_token is undefined.UNDEFINED and self.token:
            token = self.token

        webhook = await self.app.rest.edit_webhook(
            self.id,
            token=token,
            name=name,
            avatar=avatar,
            channel=channel,
            reason=reason,
        )
        assert isinstance(webhook, IncomingWebhook)
        return webhook

Edit this webhook.

Other Parameters
Returns
  • IncomingWebhook: The updated webhook object.
Raises
  • ValueError: If use_token is passed as True when IncomingWebhook.token is None.
  • hikari.errors.BadRequestError: If any invalid snowflake IDs are passed; a snowflake may be invalid due to it being outside of the range of a 64 bit integer.
  • hikari.errors.NotFoundError: If either the webhook or the channel are not found.
  • hikari.errors.ForbiddenError: If you either lack the MANAGE_WEBHOOKS permission or are not a member of the guild this webhook belongs to.
  • hikari.errors.UnauthorizedError: If you pass a token that's invalid for the target webhook.
  • hikari.errors.RateLimitTooLongError: Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
  • hikari.errors.RateLimitedError: Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
  • hikari.errors.InternalServerError: If an internal error occurs on Discord while handling the request.
#  async def edit_message(
   self,
   message: Union[hikari.messages.Message, hikari.snowflakes.Snowflake, int],
   content: Union[Any, hikari.undefined.UndefinedType, NoneType] = UNDEFINED,
   *,
   attachment: Union[hikari.files.Resource[Any], os.PathLike[str], str, bytes, bytearray, memoryview, _io.BytesIO, _io.StringIO, hikari.undefined.UndefinedType] = UNDEFINED,
   attachments: Union[Sequence[Union[hikari.files.Resource[Any], os.PathLike[str], str, bytes, bytearray, memoryview, _io.BytesIO, _io.StringIO]], hikari.undefined.UndefinedType] = UNDEFINED,
   component: Union[hikari.api.special_endpoints.ComponentBuilder, hikari.undefined.UndefinedType, NoneType] = UNDEFINED,
   components: Union[Sequence[hikari.api.special_endpoints.ComponentBuilder], hikari.undefined.UndefinedType, NoneType] = UNDEFINED,
   embed: Union[hikari.embeds.Embed, hikari.undefined.UndefinedType, NoneType] = UNDEFINED,
   embeds: Union[Sequence[hikari.embeds.Embed], hikari.undefined.UndefinedType, NoneType] = UNDEFINED,
   replace_attachments: bool = False,
   mentions_everyone: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED,
   user_mentions: Union[Sequence[Union[hikari.users.PartialUser, hikari.snowflakes.Snowflake, int]], bool, hikari.undefined.UndefinedType] = UNDEFINED,
   role_mentions: Union[Sequence[Union[hikari.guilds.PartialRole, hikari.snowflakes.Snowflake, int]], bool, hikari.undefined.UndefinedType] = UNDEFINED
) -> hikari.messages.Message:
View Source
    async def edit_message(
        self,
        message: snowflakes.SnowflakeishOr[messages_.Message],
        content: undefined.UndefinedNoneOr[typing.Any] = undefined.UNDEFINED,
        *,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedNoneOr[
            typing.Sequence[special_endpoints.ComponentBuilder]
        ] = undefined.UNDEFINED,
        embed: undefined.UndefinedNoneOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedNoneOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        replace_attachments: bool = False,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users_.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds_.PartialRole], bool]
        ] = undefined.UNDEFINED,
    ) -> messages_.Message:
        """Edit a message sent by a webhook.

        .. note::
            Mentioning everyone, roles, or users in message edits currently
            will not send a push notification showing a new mention to people
            on Discord. It will still highlight in their chat as if they
            were mentioned, however.

        .. warning::
            If you specify a text `content`, `mentions_everyone`,
            `mentions_reply`, `user_mentions`, and `role_mentions` will default
            to `False` as the message will be re-parsed for mentions. This will
            also occur if only one of the four are specified

            This is a limitation of Discord's design. If in doubt, specify all
            four of them each time.

        Parameters
        ----------
        message : hikari.snowflakes.SnowflakeishOr[hikari.messages.PartialMessage]
            The message to delete. This may be the object or the ID of
            an existing message.
        content : hikari.undefined.UndefinedNoneOr[typing.Any]
            If provided, the message contents. If
            `hikari.undefined.UNDEFINED`, then nothing will be sent
            in the content. Any other value here will be cast to a
            `str`.

            If this is a `hikari.embeds.Embed` and no `embed` nor
            no `embeds` kwarg is provided, then this will instead
            update the embed. This allows for simpler syntax when
            sending an embed alone.

            Likewise, if this is a `hikari.files.Resource`, then the
            content is instead treated as an attachment if no `attachment` and
            no `attachments` kwargs are provided.

        Other Parameters
        ----------------
        attachment : hikari.undefined.UndefinedOr[hikari.files.Resourceish]
            If provided, the attachment to set on the message. If
            `hikari.undefined.UNDEFINED`, the previous attachment, if
            present, is not changed. If this is `None`, then the
            attachment is removed, if present. Otherwise, the new attachment
            that was provided will be attached.
        attachments : hikari.undefined.UndefinedOr[typing.Sequence[hikari.files.Resourceish]]
            If provided, the attachments to set on the message. If
            `hikari.undefined.UNDEFINED`, the previous attachments, if
            present, are not changed. If this is `None`, then the
            attachments is removed, if present. Otherwise, the new attachments
            that were provided will be attached.
        component : hikari.undefined.UndefinedNoneOr[hikari.api.special_endpoints.ComponentBuilder]
            If provided, builder object of the component to set for this message.
            This component will replace any previously set components and passing
            `None` will remove all components.
        components : hikari.undefined.UndefinedNoneOr[typing.Sequence[hikari.api.special_endpoints.ComponentBuilder]]
            If provided, a sequence of the component builder objects set for
            this message. These components will replace any previously set
            components and passing `None` or an empty sequence will
            remove all components.
        embed : hikari.undefined.UndefinedNoneOr[hikari.embeds.Embed]
            If provided, the embed to set on the message. If
            `hikari.undefined.UNDEFINED`, the previous embed(s) are not changed.
            If this is `None` then any present embeds are removed.
            Otherwise, the new embed that was provided will be used as the
            replacement.
        embeds : hikari.undefined.UndefinedNoneOr[typing.Sequence[hikari.embeds.Embed]]
            If provided, the embeds to set on the message. If
            `hikari.undefined.UNDEFINED`, the previous embed(s) are not changed.
            If this is `None` then any present embeds are removed.
            Otherwise, the new embeds that were provided will be used as the
            replacement.
        replace_attachments: bool
            Whether to replace the attachments with the provided ones. Defaults
            to `False`.

            Note this will also overwrite the embed attachments.
        mentions_everyone : hikari.undefined.UndefinedOr[bool]
            If provided, sanitation for `@everyone` mentions. If
            `hikari.undefined.UNDEFINED`, then the previous setting is
            not changed. If `True`, then `@everyone`/`@here` mentions
            in the message content will show up as mentioning everyone that can
            view the chat.
        user_mentions : hikari.undefined.UndefinedOr[typing.Union[hikari.snowflakes.SnowflakeishSequence[hikari.users.PartialUser], bool]]
            If provided, and `True`, all user mentions will be detected.
            If provided, and `False`, all user mentions will be ignored
            if appearing in the message body.
            Alternatively this may be a collection of
            `hikari.snowflakes.Snowflake`, or
            `hikari.users.PartialUser` derivatives to enforce mentioning
            specific users.
        role_mentions : hikari.undefined.UndefinedOr[typing.Union[hikari.snowflakes.SnowflakeishSequence[hikari.guilds.PartialRole], bool]]
            If provided, and `True`, all role mentions will be detected.
            If provided, and `False`, all role mentions will be ignored
            if appearing in the message body.
            Alternatively this may be a collection of
            `hikari.snowflakes.Snowflake`, or
            `hikari.guilds.PartialRole` derivatives to enforce mentioning
            specific roles.

        Returns
        -------
        hikari.messages.Message
            The edited message.

        Raises
        ------
        ValueError
            If more than 100 unique objects/entities are passed for
            `role_mentions` or `user_mentions` or `token` is not available.
        TypeError
            If both `attachment` and `attachments` are specified or if both
            `embed` and `embeds` are specified.
        hikari.errors.BadRequestError
            This may be raised in several discrete situations, such as messages
            being empty with no attachments or embeds; messages with more than
            2000 characters in them, embeds that exceed one of the many embed
            limits; too many attachments; attachments that are too large;
            too many components.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If the webhook or the message are not found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """  # noqa: E501 - Line too long
        if self.token is None:
            raise ValueError("Cannot edit a message using a webhook where we don't know the token")

        return await self.app.rest.edit_webhook_message(
            self.webhook_id,
            token=self.token,
            message=message,
            content=content,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            replace_attachments=replace_attachments,
            mentions_everyone=mentions_everyone,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
        )

Edit a message sent by a webhook.

Note: Mentioning everyone, roles, or users in message edits currently will not send a push notification showing a new mention to people on Discord. It will still highlight in their chat as if they were mentioned, however.

Warning: If you specify a text content, mentions_everyone, mentions_reply, user_mentions, and role_mentions will default to False as the message will be re-parsed for mentions. This will also occur if only one of the four are specified

This is a limitation of Discord's design. If in doubt, specify all four of them each time.

Parameters
Other Parameters
Returns
Raises
  • ValueError: If more than 100 unique objects/entities are passed for role_mentions or user_mentions or token is not available.
  • TypeError: If both attachment and attachments are specified or if both embed and embeds are specified.
  • hikari.errors.BadRequestError: This may be raised in several discrete situations, such as messages being empty with no attachments or embeds; messages with more than 2000 characters in them, embeds that exceed one of the many embed limits; too many attachments; attachments that are too large; too many components.
  • hikari.errors.UnauthorizedError: If you are unauthorized to make the request (invalid/missing token).
  • hikari.errors.NotFoundError: If the webhook or the message are not found.
  • hikari.errors.RateLimitTooLongError: Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
  • hikari.errors.RateLimitedError: Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
  • hikari.errors.InternalServerError: If an internal error occurs on Discord while handling the request.
#  async def execute(
   self,
   content: Union[Any, hikari.undefined.UndefinedType] = UNDEFINED,
   *,
   username: Union[str, hikari.undefined.UndefinedType] = UNDEFINED,
   avatar_url: Union[hikari.undefined.UndefinedType, str, hikari.files.URL] = UNDEFINED,
   tts: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED,
   attachment: Union[hikari.files.Resource[Any], os.PathLike[str], str, bytes, bytearray, memoryview, _io.BytesIO, _io.StringIO, hikari.undefined.UndefinedType] = UNDEFINED,
   attachments: Union[Sequence[Union[hikari.files.Resource[Any], os.PathLike[str], str, bytes, bytearray, memoryview, _io.BytesIO, _io.StringIO]], hikari.undefined.UndefinedType] = UNDEFINED,
   component: Union[hikari.api.special_endpoints.ComponentBuilder, hikari.undefined.UndefinedType] = UNDEFINED,
   components: Union[Sequence[hikari.api.special_endpoints.ComponentBuilder], hikari.undefined.UndefinedType] = UNDEFINED,
   embed: Union[hikari.embeds.Embed, hikari.undefined.UndefinedType] = UNDEFINED,
   embeds: Union[Sequence[hikari.embeds.Embed], hikari.undefined.UndefinedType] = UNDEFINED,
   mentions_everyone: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED,
   user_mentions: Union[Sequence[Union[hikari.users.PartialUser, hikari.snowflakes.Snowflake, int]], bool, hikari.undefined.UndefinedType] = UNDEFINED,
   role_mentions: Union[Sequence[Union[hikari.guilds.PartialRole, hikari.snowflakes.Snowflake, int]], bool, hikari.undefined.UndefinedType] = UNDEFINED,
   flags: Union[hikari.undefined.UndefinedType, int, hikari.messages.MessageFlag] = UNDEFINED
) -> hikari.messages.Message:
View Source
    async def execute(
        self,
        content: undefined.UndefinedOr[typing.Any] = undefined.UNDEFINED,
        *,
        username: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        avatar_url: typing.Union[undefined.UndefinedType, str, files.URL] = undefined.UNDEFINED,
        tts: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        attachment: undefined.UndefinedOr[files_.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files_.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedOr[typing.Sequence[special_endpoints.ComponentBuilder]] = undefined.UNDEFINED,
        embed: undefined.UndefinedOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users_.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds_.PartialRole], bool]
        ] = undefined.UNDEFINED,
        flags: typing.Union[undefined.UndefinedType, int, messages_.MessageFlag] = undefined.UNDEFINED,
    ) -> messages_.Message:
        """Execute the webhook to create a message.

        .. warning::
            At the time of writing, `username` and `avatar_url` are ignored for
            interaction webhooks.

            Additionally, flags this can only be set for interaction webhooks
            and the only settable flag is EPHEMERAL; this field is just
            ignored for non-interaction webhooks.

        Parameters
        ----------
        content : hikari.undefined.UndefinedOr[typing.Any]
            If provided, the message contents. If
            `hikari.undefined.UNDEFINED`, then nothing will be sent
            in the content. Any other value here will be cast to a
            `str`.

            If this is a `hikari.embeds.Embed` and no `embed` kwarg is
            provided, then this will instead update the embed. This allows for
            simpler syntax when sending an embed alone.

            Likewise, if this is a `hikari.files.Resource`, then the
            content is instead treated as an attachment if no `attachment` and
            no `attachments` kwargs are provided.

        Other Parameters
        ----------------
        username : hikari.undefined.UndefinedOr[str]
            If provided, the username to override the webhook's username
            for this request.
        avatar_url : typing.Union[hikari.undefined.UndefinedType, hikari.files.URL, str]
            If provided, the url of an image to override the webhook's
            avatar with for this request.
        tts : hikari.undefined.UndefinedOr[bool]
            If provided, whether the message will be sent as a TTS message.
        attachment : hikari.undefined.UndefinedOr[hikari.files.Resourceish]
            If provided, the message attachment. This can be a resource,
            or string of a path on your computer or a URL.
        attachments : hikari.undefined.UndefinedOr[typing.Sequence[hikari.files.Resourceish]]
            If provided, the message attachments. These can be resources, or
            strings consisting of paths on your computer or URLs.
        component : hikari.undefined.UndefinedOr[hikari.api.special_endpoints.ComponentBuilder]
            If provided, builder object of the component to include in this message.
        components : hikari.undefined.UndefinedOr[typing.Sequence[hikari.api.special_endpoints.ComponentBuilder]]
            If provided, a sequence of the component builder objects to include
            in this message.
        embed : hikari.undefined.UndefinedOr[hikari.embeds.Embed]
            If provided, the message embed.
        embeds : hikari.undefined.UndefinedOr[typing.Sequence[hikari.embeds.Embed]]
            If provided, the message embeds.
        mentions_everyone : hikari.undefined.UndefinedOr[bool]
            If provided, whether the message should parse @everyone/@here
            mentions.
        user_mentions : hikari.undefined.UndefinedOr[typing.Union[hikari.snowflakes.SnowflakeishSequence[hikari.users.PartialUser], bool]]
            If provided, and `True`, all mentions will be parsed.
            If provided, and `False`, no mentions will be parsed.
            Alternatively this may be a collection of
            `hikari.snowflakes.Snowflake`, or
            `hikari.users.PartialUser` derivatives to enforce mentioning
            specific users.
        role_mentions : hikari.undefined.UndefinedOr[typing.Union[hikari.snowflakes.SnowflakeishSequence[hikari.guilds.PartialRole], bool]]
            If provided, and `True`, all mentions will be parsed.
            If provided, and `False`, no mentions will be parsed.
            Alternatively this may be a collection of
            `hikari.snowflakes.Snowflake`, or
            `hikari.guilds.PartialRole` derivatives to enforce mentioning
            specific roles.
        flags : typing.Union[hikari.undefined.UndefinedType, int, hikari.messages.MessageFlag]
            The flags to set for this webhook message.

        Returns
        -------
        hikari.messages.Message
            The created message object.

        Raises
        ------
        hikari.errors.NotFoundError
            If the current webhook is not found.
        hikari.errors.BadRequestError
            This can be raised if the file is too large; if the embed exceeds
            the defined limits; if the message content is specified only and
            empty or greater than `2000` characters; if neither content, file
            or embeds are specified.
            If any invalid snowflake IDs are passed; a snowflake may be invalid
            due to it being outside of the range of a 64 bit integer.
        hikari.errors.UnauthorizedError
            If you pass a token that's invalid for the target webhook.
        ValueError
            If either `ExecutableWebhook.token` is `None` or more than 100 unique
            objects/entities are passed for `role_mentions` or `user_mentions or
            if `token` is not available.
        TypeError
            If both `attachment` and `attachments`, `component` and `components`
            or `embed` and `embeds` are specified.
        """  # noqa: E501 - Line too long
        if not self.token:
            raise ValueError("Cannot send a message using a webhook where we don't know the token")

        return await self.app.rest.execute_webhook(
            webhook=self.webhook_id,
            token=self.token,
            content=content,
            username=username,
            avatar_url=avatar_url,
            tts=tts,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            mentions_everyone=mentions_everyone,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
            flags=flags,
        )

Execute the webhook to create a message.

Warning: At the time of writing, username and avatar_url are ignored for interaction webhooks.

Additionally, flags this can only be set for interaction webhooks and the only settable flag is EPHEMERAL; this field is just ignored for non-interaction webhooks.

Parameters
  • content (hikari.undefined.UndefinedOr[typing.Any]): If provided, the message contents. If hikari.undefined.UNDEFINED, then nothing will be sent in the content. Any other value here will be cast to a str.

    If this is a hikari.embeds.Embed and no embed kwarg is provided, then this will instead update the embed. This allows for simpler syntax when sending an embed alone.

    Likewise, if this is a hikari.files.Resource, then the content is instead treated as an attachment if no attachment and no attachments kwargs are provided.

Other Parameters
Returns
Raises
  • hikari.errors.NotFoundError: If the current webhook is not found.
  • hikari.errors.BadRequestError: This can be raised if the file is too large; if the embed exceeds the defined limits; if the message content is specified only and empty or greater than 2000 characters; if neither content, file or embeds are specified. If any invalid snowflake IDs are passed; a snowflake may be invalid due to it being outside of the range of a 64 bit integer.
  • hikari.errors.UnauthorizedError: If you pass a token that's invalid for the target webhook.
  • ValueError: If either ExecutableWebhook.token is None or more than 100 unique objects/entities are passed for role_mentions or user_mentions or iftoken` is not available.
  • TypeError: If both attachment and attachments, component and components or embed and embeds are specified.
#  async def fetch_channel(
   self
) -> Union[hikari.channels.GuildTextChannel, hikari.channels.GuildNewsChannel]:
View Source
    async def fetch_channel(self) -> channels_.WebhookChannelT:
        """Fetch the channel this webhook is for.

        Returns
        -------
        hikari.channels.WebhookChannelT
            The object of the channel this webhook targets.

        Raises
        ------
        hikari.errors.ForbiddenError
            If you don't have access to the channel this webhook belongs to.
        hikari.errors.NotFoundError
            If the channel this message was created in does not exist.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        channel = await self.app.rest.fetch_channel(self.channel_id)
        assert isinstance(channel, channels_.WebhookChannelTypes)
        return channel

Fetch the channel this webhook is for.

Returns
Raises
  • hikari.errors.ForbiddenError: If you don't have access to the channel this webhook belongs to.
  • hikari.errors.NotFoundError: If the channel this message was created in does not exist.
  • hikari.errors.UnauthorizedError: If you are unauthorized to make the request (invalid/missing token).
  • hikari.errors.RateLimitTooLongError: Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
  • hikari.errors.RateLimitedError: Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
  • hikari.errors.InternalServerError: If an internal error occurs on Discord while handling the request.
#  async def fetch_message(
   self,
   message: Union[hikari.messages.Message, hikari.snowflakes.Snowflake, int]
) -> hikari.messages.Message:
View Source
    async def fetch_message(self, message: snowflakes.SnowflakeishOr[messages_.Message]) -> messages_.Message:
        """Fetch an old message sent by the webhook.

        Parameters
        ----------
        message : hikari.snowflakes.SnowflakeishOr[hikari.messages.PartialMessage]
            The message to fetch. This may be the object or the ID of an
            existing channel.

        Returns
        -------
        hikari.messages.Message
            The requested message.

        Raises
        ------
        ValueError
            If `token` is not available.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If the webhook is not found or the webhook's message wasn't found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        if self.token is None:
            raise ValueError("Cannot fetch a message using a webhook where we don't know the token")

        return await self.app.rest.fetch_webhook_message(self.webhook_id, token=self.token, message=message)

Fetch an old message sent by the webhook.

Parameters
Returns
Raises
  • ValueError: If token is not available.
  • hikari.errors.UnauthorizedError: If you are unauthorized to make the request (invalid/missing token).
  • hikari.errors.NotFoundError: If the webhook is not found or the webhook's message wasn't found.
  • hikari.errors.RateLimitTooLongError: Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
  • hikari.errors.RateLimitedError: Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
  • hikari.errors.InternalServerError: If an internal error occurs on Discord while handling the request.
#  async def fetch_self(
   self,
   *,
   use_token: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED
) -> hikari.webhooks.IncomingWebhook:
View Source
    async def fetch_self(self, *, use_token: undefined.UndefinedOr[bool] = undefined.UNDEFINED) -> IncomingWebhook:
        """Fetch this webhook.

        Other Parameters
        ----------------
        use_token : hikari.undefined.UndefinedOr[bool]
            If set to `True` then the webhook's token will be used for
            this request; if set to `False` then bot authorization will
            be used; if not specified then the webhook's token will be used for
            the request if it's set else bot authorization.

        Returns
        -------
        IncomingWebhook
            The requested webhook object.

        Raises
        ------
        ValueError
            If `use_token` is passed as `True` when `Webhook.token`
            is `None`.
        hikari.errors.ForbiddenError
            If you're not in the guild that owns this webhook or
            lack the `MANAGE_WEBHOOKS` permission.
        hikari.errors.NotFoundError
            If the webhook is not found.
        hikari.errors.UnauthorizedError
            If you pass a token that's invalid for the target webhook.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        token: undefined.UndefinedOr[str] = undefined.UNDEFINED
        if use_token:
            if self.token is None:
                raise ValueError("This webhook's token is unknown, so cannot be used")
            token = self.token

        elif use_token is undefined.UNDEFINED and self.token:
            token = self.token

        webhook = await self.app.rest.fetch_webhook(self.id, token=token)
        assert isinstance(webhook, IncomingWebhook)
        return webhook

Fetch this webhook.

Other Parameters
  • use_token (hikari.undefined.UndefinedOr[bool]): If set to True then the webhook's token will be used for this request; if set to False then bot authorization will be used; if not specified then the webhook's token will be used for the request if it's set else bot authorization.
Returns
  • IncomingWebhook: The requested webhook object.
Raises
  • ValueError: If use_token is passed as True when Webhook.token is None.
  • hikari.errors.ForbiddenError: If you're not in the guild that owns this webhook or lack the MANAGE_WEBHOOKS permission.
  • hikari.errors.NotFoundError: If the webhook is not found.
  • hikari.errors.UnauthorizedError: If you pass a token that's invalid for the target webhook.
  • hikari.errors.RateLimitTooLongError: Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
  • hikari.errors.RateLimitedError: Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
  • hikari.errors.InternalServerError: If an internal error occurs on Discord while handling the request.
#  def make_avatar_url(
   self,
   ext: str = 'png',
   size: int = 4096
) -> Optional[hikari.files.URL]:
View Source
    def make_avatar_url(self, ext: str = "png", size: int = 4096) -> typing.Optional[files_.URL]:
        """Generate the avatar URL for this webhook's custom avatar if set.

        If no avatar is specified, return `None`. In this case, you should
        use `default_avatar` instead.

        Parameters
        ----------
        ext : str
            The extension to use for this URL, defaults to `png`.
            Supports `png`, `jpeg`, `jpg` and `webp`.
        size : int
            The size to set for the URL, defaults to `4096`.
            Can be any power of two between 16 and 4096.
            Will be ignored for default avatars.

        Returns
        -------
        typing.Optional[hikari.files.URL]
            The URL of the resource. `None` if no avatar is set (in
            this case, use the `default_avatar` instead).

        Raises
        ------
        ValueError
            If `size` is not a power of two between 16 and 4096 (inclusive).
        """
        if self.avatar_hash is None:
            return None

        return routes.CDN_USER_AVATAR.compile_to_file(
            urls.CDN_URL,
            user_id=self.id,
            hash=self.avatar_hash,
            size=size,
            file_format=ext,
        )

Generate the avatar URL for this webhook's custom avatar if set.

If no avatar is specified, return None. In this case, you should use default_avatar instead.

Parameters
  • ext (str): The extension to use for this URL, defaults to png. Supports png, jpeg, jpg and webp.
  • size (int): The size to set for the URL, defaults to 4096. Can be any power of two between 16 and 4096. Will be ignored for default avatars.
Returns
  • typing.Optional[hikari.files.URL]: The URL of the resource. None if no avatar is set (in this case, use the default_avatar instead).
Raises
  • ValueError: If size is not a power of two between 16 and 4096 (inclusive).
#  
@attr_extensions.with_copy
@attr.define(hash=True, kw_only=True, weakref_slot=False)
class PartialWebhook(hikari.snowflakes.Unique):
View Source
@attr_extensions.with_copy
@attr.define(hash=True, kw_only=True, weakref_slot=False)
class PartialWebhook(snowflakes.Unique):
    """Base class for all webhook implementations."""

    app: traits.RESTAware = attr.field(
        repr=False, eq=False, hash=False, metadata={attr_extensions.SKIP_DEEP_COPY: True}
    )
    """The client application that models may use for procedures."""

    id: snowflakes.Snowflake = attr.field(hash=True, repr=True)
    """The ID of this entity."""

    type: typing.Union[WebhookType, int] = attr.field(eq=False, hash=False, repr=True)
    """The type of the webhook."""

    name: str = attr.field(eq=False, hash=False, repr=True)
    """The name of the webhook."""

    avatar_hash: typing.Optional[str] = attr.field(eq=False, hash=False, repr=False)
    """The avatar hash of the webhook."""

    application_id: typing.Optional[snowflakes.Snowflake] = attr.field(eq=False, hash=False, repr=False)
    """The ID of the application that created this webhook."""

    def __str__(self) -> str:
        return self.name if self.name is not None else f"Unnamed webhook ID {self.id}"

    @property
    def mention(self) -> str:
        """Return a raw mention string for the given webhook's user.

        .. note::
            This exists purely for consistency. Webhooks do not receive events
            from the gateway, and without some bot backend to support it, will
            not be able to detect mentions of their webhook.

        Example
        -------
        ```py
        >>> some_webhook.mention
        '<@123456789123456789>'
        ```
        """
        return f"<@{self.id}>"

    @property
    def avatar_url(self) -> typing.Optional[files_.URL]:
        """URL for this webhook's avatar, if set.

        May be `None` if no avatar is set. In this case, you should use
        `default_avatar_url` instead.
        """
        return self.make_avatar_url()

    @property
    def default_avatar_url(self) -> files_.URL:
        """Default avatar URL for the user."""  # noqa: D401 - Imperative mood
        return routes.CDN_DEFAULT_USER_AVATAR.compile_to_file(
            urls.CDN_URL,
            discriminator=0,
            file_format="png",
        )

    def make_avatar_url(self, ext: str = "png", size: int = 4096) -> typing.Optional[files_.URL]:
        """Generate the avatar URL for this webhook's custom avatar if set.

        If no avatar is specified, return `None`. In this case, you should
        use `default_avatar` instead.

        Parameters
        ----------
        ext : str
            The extension to use for this URL, defaults to `png`.
            Supports `png`, `jpeg`, `jpg` and `webp`.
        size : int
            The size to set for the URL, defaults to `4096`.
            Can be any power of two between 16 and 4096.
            Will be ignored for default avatars.

        Returns
        -------
        typing.Optional[hikari.files.URL]
            The URL of the resource. `None` if no avatar is set (in
            this case, use the `default_avatar` instead).

        Raises
        ------
        ValueError
            If `size` is not a power of two between 16 and 4096 (inclusive).
        """
        if self.avatar_hash is None:
            return None

        return routes.CDN_USER_AVATAR.compile_to_file(
            urls.CDN_URL,
            user_id=self.id,
            hash=self.avatar_hash,
            size=size,
            file_format=ext,
        )

Base class for all webhook implementations.

Variables and properties

The client application that models may use for procedures.

#  application_id: Optional[hikari.snowflakes.Snowflake]

The ID of the application that created this webhook.

#  avatar_hash: Optional[str]

The avatar hash of the webhook.

#  avatar_url: Optional[hikari.files.URL]

URL for this webhook's avatar, if set.

May be None if no avatar is set. In this case, you should use default_avatar_url instead.

#  created_at: datetime.datetime

When the object was created.

#  default_avatar_url: hikari.files.URL

Default avatar URL for the user.

The ID of this entity.

#  mention: str

Return a raw mention string for the given webhook's user.

Note: This exists purely for consistency. Webhooks do not receive events from the gateway, and without some bot backend to support it, will not be able to detect mentions of their webhook.

Example
>>> some_webhook.mention
'<@123456789123456789>'
#  name: str

The name of the webhook.

The type of the webhook.

Methods
#  def __init__(
   self,
   *,
   app: hikari.traits.RESTAware,
   id: hikari.snowflakes.Snowflake,
   type: Union[hikari.webhooks.WebhookType, int],
   name: str,
   avatar_hash: Optional[str],
   application_id: Optional[hikari.snowflakes.Snowflake]
):
View Source
def __init__(self, *, app, id, type, name, avatar_hash, application_id):
    self.app = app
    self.id = id
    self.type = type
    self.name = name
    self.avatar_hash = avatar_hash
    self.application_id = application_id

Method generated by attrs for class PartialWebhook.

#  def make_avatar_url(
   self,
   ext: str = 'png',
   size: int = 4096
) -> Optional[hikari.files.URL]:
View Source
    def make_avatar_url(self, ext: str = "png", size: int = 4096) -> typing.Optional[files_.URL]:
        """Generate the avatar URL for this webhook's custom avatar if set.

        If no avatar is specified, return `None`. In this case, you should
        use `default_avatar` instead.

        Parameters
        ----------
        ext : str
            The extension to use for this URL, defaults to `png`.
            Supports `png`, `jpeg`, `jpg` and `webp`.
        size : int
            The size to set for the URL, defaults to `4096`.
            Can be any power of two between 16 and 4096.
            Will be ignored for default avatars.

        Returns
        -------
        typing.Optional[hikari.files.URL]
            The URL of the resource. `None` if no avatar is set (in
            this case, use the `default_avatar` instead).

        Raises
        ------
        ValueError
            If `size` is not a power of two between 16 and 4096 (inclusive).
        """
        if self.avatar_hash is None:
            return None

        return routes.CDN_USER_AVATAR.compile_to_file(
            urls.CDN_URL,
            user_id=self.id,
            hash=self.avatar_hash,
            size=size,
            file_format=ext,
        )

Generate the avatar URL for this webhook's custom avatar if set.

If no avatar is specified, return None. In this case, you should use default_avatar instead.

Parameters
  • ext (str): The extension to use for this URL, defaults to png. Supports png, jpeg, jpg and webp.
  • size (int): The size to set for the URL, defaults to 4096. Can be any power of two between 16 and 4096. Will be ignored for default avatars.
Returns
  • typing.Optional[hikari.files.URL]: The URL of the resource. None if no avatar is set (in this case, use the default_avatar instead).
Raises
  • ValueError: If size is not a power of two between 16 and 4096 (inclusive).
#  
@typing.final
class WebhookType(builtins.int, hikari.internal.enums.Enum):
View Source
@typing.final
class WebhookType(int, enums.Enum):
    """Types of webhook."""

    INCOMING = 1
    """Incoming webhook."""

    CHANNEL_FOLLOWER = 2
    """Channel Follower webhook."""

    APPLICATION = 3
    """Application webhook (from the interactions flow)."""

Types of webhook.

Variables and properties
#  APPLICATION

Application webhook (from the interactions flow).

#  CHANNEL_FOLLOWER

Channel Follower webhook.

#  INCOMING

Incoming webhook.

#  denominator

the denominator of a rational number in lowest terms

#  imag

the imaginary part of a complex number

#  name: str

Return the name of the enum member as a str.

#  numerator

the numerator of a rational number in lowest terms

#  real

the real part of a complex number

#  value

Return the value of the enum member.

Methods
#  def __init__(cls, value: Any):
View Source
    def __call__(cls, value: typing.Any) -> typing.Any:
        """Cast a value to the enum, returning the raw value that was passed if value not found."""
        try:
            return cls._value_to_member_map_[value]
        except KeyError:
            # If we can't find the value, just return what got casted in
            return value

Cast a value to the enum, returning the raw value that was passed if value not found.

#  def as_integer_ratio(self, /):

Return integer ratio.

Return a pair of integers, whose ratio is exactly equal to the original int and with a positive denominator.

>>> (10).as_integer_ratio()
(10, 1)
>>> (-10).as_integer_ratio()
(-10, 1)
>>> (0).as_integer_ratio()
(0, 1)
#  def bit_length(self, /):

Number of bits necessary to represent self in binary.

>>> bin(37)
'0b100101'
>>> (37).bit_length()
6
#  def conjugate(unknown):

Returns self, the complex conjugate of any int.

#  def from_bytes(type, /, bytes, byteorder, *, signed=False):

Return the integer represented by the given array of bytes.

bytes Holds the array of bytes to convert. The argument must either support the buffer protocol or be an iterable object producing bytes. Bytes and bytearray are examples of built-in objects that support the buffer protocol. byteorder The byte order used to represent the integer. If byteorder is 'big', the most significant byte is at the beginning of the byte array. If byteorder is 'little', the most significant byte is at the end of the byte array. To request the native byte order of the host system, use `sys.byteorder' as the byte order value. signed Indicates whether two's complement is used to represent the integer.

#  def to_bytes(self, /, length, byteorder, *, signed=False):

Return an array of bytes representing an integer.

length Length of bytes object to use. An OverflowError is raised if the integer is not representable with the given number of bytes. byteorder The byte order used to represent the integer. If byteorder is 'big', the most significant byte is at the beginning of the byte array. If byteorder is 'little', the most significant byte is at the end of the byte array. To request the native byte order of the host system, use `sys.byteorder' as the byte order value. signed Determines whether two's complement is used to represent the integer. If signed is False and a negative integer is given, an OverflowError is raised.