Back to top

hikari.events.message_events

Events that fire if messages are sent/updated/deleted.

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.
"""Events that fire if messages are sent/updated/deleted."""

from __future__ import annotations

__all__: typing.Sequence[str] = (
    "MessageEvent",
    "MessageCreateEvent",
    "MessageUpdateEvent",
    "MessageDeleteEvent",
    "GuildMessageCreateEvent",
    "GuildMessageUpdateEvent",
    "GuildMessageDeleteEvent",
    "GuildBulkMessageDeleteEvent",
    "DMMessageCreateEvent",
    "DMMessageUpdateEvent",
    "DMMessageDeleteEvent",
)

import abc
import typing

import attr

from hikari import channels
from hikari import intents
from hikari import snowflakes
from hikari import traits
from hikari import undefined
from hikari.events import base_events
from hikari.events import shard_events
from hikari.internal import attr_extensions

if typing.TYPE_CHECKING:
    from hikari import embeds as embeds_
    from hikari import guilds
    from hikari import messages
    from hikari import users
    from hikari.api import shard as shard_


@base_events.requires_intents(intents.Intents.DM_MESSAGES, intents.Intents.GUILD_MESSAGES)
class MessageEvent(shard_events.ShardEvent, abc.ABC):
    """Any event that concerns manipulation of messages."""

    __slots__: typing.Sequence[str] = ()

    @property
    @abc.abstractmethod
    def channel_id(self) -> snowflakes.Snowflake:
        """ID of the channel that this event concerns."""

    @property
    @abc.abstractmethod
    def message_id(self) -> snowflakes.Snowflake:
        """ID of the message that this event concerns."""


@base_events.requires_intents(intents.Intents.DM_MESSAGES, intents.Intents.GUILD_MESSAGES)
class MessageCreateEvent(MessageEvent, abc.ABC):
    """Event that is fired when a message is created."""

    __slots__: typing.Sequence[str] = ()

    @property
    def app(self) -> traits.RESTAware:
        # <<inherited docstring from Event>>.
        return self.message.app

    @property
    def author(self) -> users.User:
        """User that sent the message."""
        return self.message.author

    @property
    def author_id(self) -> snowflakes.Snowflake:
        """ID of the author of the message this event concerns."""
        return self.author.id

    @property
    def channel_id(self) -> snowflakes.Snowflake:
        # <<inherited docstring from MessageEvent>>
        return self.message.channel_id

    @property
    def content(self) -> typing.Optional[str]:
        """Content of the message.

        The content of the message, if present. This will be `None`
        if no content is present (e.g. if only an embed was sent).
        """
        return self.message.content

    @property
    def embeds(self) -> typing.Sequence[embeds_.Embed]:
        """Sequence of embeds in the message."""
        return self.message.embeds

    @property
    def is_bot(self) -> bool:
        """Return `True` if the message is from a bot."""
        return self.message.author.is_bot

    @property
    def is_human(self) -> bool:
        """Return `True` if the message was created by a human."""
        # Not second-guessing some weird edge case will occur in the future with this,
        # so I am being safe rather than sorry.
        return not self.message.author.is_bot and self.message.webhook_id is None

    @property
    def is_webhook(self) -> bool:
        """Return `True` if the message was created by a webhook."""
        return self.message.webhook_id is not None

    @property
    @abc.abstractmethod
    def message(self) -> messages.Message:
        """Message that was sent in the event."""

    @property
    def message_id(self) -> snowflakes.Snowflake:
        """ID of the message that this event concerns."""
        return self.message.id


@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.GUILD_MESSAGES)
class GuildMessageCreateEvent(MessageCreateEvent):
    """Event that is fired when a message is created within a guild.

    This contains the full message in the internal `message` attribute.
    """

    message: messages.Message = attr.field()
    # <<inherited docstring from MessageCreateEvent>>

    shard: shard_.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from ShardEvent>>

    @property
    def author(self) -> users.User:
        """User object of the user that sent the message."""
        return self.message.author

    @property
    def member(self) -> typing.Optional[guilds.Member]:
        """Member object of the user that sent the message."""
        return self.message.member

    @property
    def guild_id(self) -> snowflakes.Snowflake:
        """ID of the guild that this event occurred in."""
        guild_id = self.message.guild_id
        # Always present on guild events
        assert isinstance(guild_id, snowflakes.Snowflake), "no guild_id attribute set"
        return guild_id

    def get_channel(self) -> typing.Optional[channels.TextableGuildChannel]:
        """Channel that the message was sent in, if known.

        Returns
        -------
        typing.Optional[hikari.channels.TextableGuildChannel]
            The channel that the message was sent in, if known and cached,
            otherwise, `None`.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        channel = self.app.cache.get_guild_channel(self.channel_id)
        assert channel is None or isinstance(
            channel, channels.TextableGuildChannel
        ), f"Cached channel ID is not a TextableGuildChannel, but a {type(channel).__name__}!"
        return channel

    def get_guild(self) -> typing.Optional[guilds.GatewayGuild]:
        """Get the cached guild that this event occurred in, if known.

        .. note::
            This will require the `GUILDS` intent to be specified on start-up
            in order to be known.

        Returns
        -------
        typing.Optional[hikari.guilds.GatewayGuild]
            The guild that this event occurred in, if cached. Otherwise,
            `None` instead.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        return self.app.cache.get_guild(self.guild_id)

    def get_member(self) -> typing.Optional[guilds.Member]:
        """Get the member that sent this message from the cache if available.

        Returns
        -------
        typing.Optional[hikari.guilds.Member]
            Cached object of the member that sent the message if found.
        """
        if isinstance(self.app, traits.CacheAware):
            return self.app.cache.get_member(self.guild_id, self.message.author.id)

        return None


@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.DM_MESSAGES)
class DMMessageCreateEvent(MessageCreateEvent):
    """Event that is fired when a message is created within a DM.

    This contains the full message in the internal `message` attribute.
    """

    message: messages.Message = attr.field()
    # <<inherited docstring from MessageCreateEvent>>

    shard: shard_.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from ShardEvent>>


@base_events.requires_intents(intents.Intents.DM_MESSAGES, intents.Intents.GUILD_MESSAGES)
class MessageUpdateEvent(MessageEvent, abc.ABC):
    """Event that is fired when a message is updated.

    .. note::
        Less information will be available here than in the creation event
        due to Discord limitations.
    """

    __slots__: typing.Sequence[str] = ()

    @property
    def app(self) -> traits.RESTAware:
        # <<inherited docstring from Event>>.
        return self.message.app

    @property
    def author(self) -> undefined.UndefinedOr[users.User]:
        """User that sent the message.

        This will be `hikari.undefined.UNDEFINED` in some cases such as when Discord
        updates a message with an embed URL preview.
        """
        return self.message.author

    @property
    def author_id(self) -> undefined.UndefinedOr[snowflakes.Snowflake]:
        """ID of the author that triggered this event.

        This will be `hikari.undefined.UNDEFINED` in some cases such as when Discord
        updates a message with an embed URL preview.
        """
        author = self.message.author
        return author.id if author is not undefined.UNDEFINED else undefined.UNDEFINED

    @property
    def channel_id(self) -> snowflakes.Snowflake:
        # <<inherited docstring from MessageEvent>>.
        return self.message.channel_id

    @property
    def content(self) -> undefined.UndefinedNoneOr[str]:
        """Content of the message.

        The content of the message, if present. This may be `None`
        if no content is present (e.g. if only an embed was sent).

        If not part of the update, then this will be
        `hikari.undefined.UNDEFINED` instead.
        """
        return self.message.content

    @property
    def embeds(self) -> undefined.UndefinedOr[typing.Sequence[embeds_.Embed]]:
        """Sequence of embeds in the message.

        If the embeds were not changed in this event, then this may instead be
        `hikari.undefined.UNDEFINED`.
        """
        return self.message.embeds

    @property
    def is_bot(self) -> undefined.UndefinedOr[bool]:
        """Whether the message is from a bot.

        If the author is not known, due to the update event being caused
        by Discord adding an embed preview to accompany a URL, then this
        will return `hikari.undefined.UNDEFINED` instead.
        """
        if (author := self.message.author) is not undefined.UNDEFINED:
            return author.is_bot

        return undefined.UNDEFINED

    @property
    def is_human(self) -> undefined.UndefinedOr[bool]:
        """Whether the message was created by a human.

        If the author is not known, due to the update event being caused
        by Discord adding an embed preview to accompany a URL, then this
        may return `hikari.undefined.UNDEFINED` instead.
        """
        # Not second-guessing some weird edge case will occur in the future with this,
        # so I am being safe rather than sorry.
        if (webhook_id := self.message.webhook_id) is not undefined.UNDEFINED:
            return webhook_id is None

        if (author := self.message.author) is not undefined.UNDEFINED:
            return not author.is_bot

        return undefined.UNDEFINED

    @property
    def is_webhook(self) -> undefined.UndefinedOr[bool]:
        """Whether the message was created by a webhook.

        If the author is not known, due to the update event being caused
        by Discord adding an embed preview to accompany a URL, then this
        may return `hikari.undefined.UNDEFINED` instead.
        """
        if (webhook_id := self.message.webhook_id) is not undefined.UNDEFINED:
            return webhook_id is not None

        return undefined.UNDEFINED

    @property
    @abc.abstractmethod
    def message(self) -> messages.PartialMessage:
        """Partial message that was sent in the event."""

    @property
    def message_id(self) -> snowflakes.Snowflake:
        """ID of the message that this event concerns."""
        return self.message.id


@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.GUILD_MESSAGES)
class GuildMessageUpdateEvent(MessageUpdateEvent):
    """Event that is fired when a message is updated in a guild.

    .. note::
        Less information will be available here than in the creation event
        due to Discord limitations.
    """

    old_message: typing.Optional[messages.PartialMessage] = attr.field()
    """The old message object.

    This will be `None` if the message missing from the cache.
    """

    message: messages.PartialMessage = attr.field()
    # <<inherited docstring from MessageUpdateEvent>>

    shard: shard_.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from ShardEvent>>

    @property
    def member(self) -> undefined.UndefinedNoneOr[guilds.Member]:
        """Member that sent the message if provided by the event.

        If the message is not in a guild, this will be `None`.

        This will also be `hikari.undefined.UNDEFINED` in some cases such as when Discord
        updates a message with an embed URL preview.
        """
        return self.message.member

    def get_member(self) -> typing.Optional[guilds.Member]:
        """Get the member that sent this message from the cache if available.

        Returns
        -------
        typing.Optional[hikari.guilds.Member]
            Cached object of the member that sent the message if found.
        """
        if self.message.author is not undefined.UNDEFINED and isinstance(self.app, traits.CacheAware):
            return self.app.cache.get_member(self.guild_id, self.message.author.id)

        return None

    @property
    def guild_id(self) -> snowflakes.Snowflake:
        """ID of the guild that this event occurred in."""
        guild_id = self.message.guild_id
        # Always present on guild events
        assert isinstance(guild_id, snowflakes.Snowflake), f"expected guild_id, got {guild_id}"
        return guild_id

    def get_channel(self) -> typing.Optional[channels.TextableGuildChannel]:
        """Channel that the message was sent in, if known.

        Returns
        -------
        typing.Optional[hikari.channels.TextableGuildChannel]
            The channel that the message was sent in, if known and cached,
            otherwise, `None`.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        channel = self.app.cache.get_guild_channel(self.channel_id)
        assert channel is None or isinstance(
            channel, channels.TextableGuildChannel
        ), f"Cached channel ID is not a TextableGuildChannel, but a {type(channel).__name__}!"
        return channel

    def get_guild(self) -> typing.Optional[guilds.GatewayGuild]:
        """Get the cached guild that this event occurred in, if known.

        .. note::
            This will require the `GUILDS` intent to be specified on start-up
            in order to be known.

        Returns
        -------
        typing.Optional[hikari.guilds.GatewayGuild]
            The guild that this event occurred in, if cached. Otherwise,
            `None` instead.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        return self.app.cache.get_guild(self.guild_id)


@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.DM_MESSAGES)
class DMMessageUpdateEvent(MessageUpdateEvent):
    """Event that is fired when a message is updated in a DM.

    .. note::
        Less information will be available here than in the creation event
        due to Discord limitations.
    """

    old_message: typing.Optional[messages.PartialMessage] = attr.field()
    """The old message object.

    This will be `None` if the message missing from the cache.
    """

    message: messages.PartialMessage = attr.field()
    # <<inherited docstring from MessageUpdateEvent>>

    shard: shard_.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from ShardEvent>>


@base_events.requires_intents(intents.Intents.GUILD_MESSAGES, intents.Intents.DM_MESSAGES)
class MessageDeleteEvent(MessageEvent, abc.ABC):
    """Special event that is triggered when a message gets deleted.

    .. note::
        Due to Discord limitations, most message information is unavailable
        during deletion events.
    """

    __slots__: typing.Sequence[str] = ()

    @property
    @abc.abstractmethod
    def message_id(self) -> snowflakes.Snowflake:
        """ID of the message that was deleted."""

    @property
    @abc.abstractmethod
    def old_message(self) -> typing.Optional[messages.Message]:
        """Object of the message that was deleted.

        Will be `None` if the message was not found in the cache.
        """


@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.GUILD_MESSAGES)
class GuildMessageDeleteEvent(MessageDeleteEvent):
    """Event that is triggered if a message is deleted in a guild.

    .. note::
        Due to Discord limitations, most message information is unavailable
        during deletion events.
    """

    app: traits.RESTAware = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from Event>>

    channel_id: snowflakes.Snowflake = attr.field()
    # <<inherited docstring from MessageEvent>>

    guild_id: snowflakes.Snowflake = attr.field()
    """ID of the guild that this event occurred in."""

    message_id: snowflakes.Snowflake = attr.field()
    # <<inherited docstring from MessageDeleteEvent>>

    old_message: typing.Optional[messages.Message] = attr.field()
    # <<inherited docstring from MessageDeleteEvent>>

    shard: shard_.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from ShardEvent>>

    def get_channel(self) -> typing.Optional[channels.TextableGuildChannel]:
        """Get the cached channel the message were sent in, if known.

        Returns
        -------
        typing.Optional[hikari.channels.TextableGuildChannel]
            The channel the messages were sent in, or `None` if not
            known/cached.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        channel = self.app.cache.get_guild_channel(self.channel_id)
        assert channel is None or isinstance(
            channel, channels.TextableGuildChannel
        ), f"Cached channel ID is not a TextableGuildChannel, but a {type(channel).__name__}!"
        return channel

    def get_guild(self) -> typing.Optional[guilds.GatewayGuild]:
        """Get the cached guild this event corresponds to, if known.

        .. note::
            You will need `hikari.intents.Intents.GUILDS` enabled to receive this
            information.

        Returns
        -------
        hikari.guilds.GatewayGuild
            The gateway guild that this event corresponds to, if known and
            cached.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        return self.app.cache.get_guild(self.guild_id)


@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.DM_MESSAGES)
class DMMessageDeleteEvent(MessageDeleteEvent):
    """Event that is triggered if a message is deleted in a DM.

    .. note::
        Due to Discord limitations, most message information is unavailable
        during deletion events.
    """

    app: traits.RESTAware = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from Event>>

    channel_id: snowflakes.Snowflake = attr.field()
    # <<inherited docstring from MessageEvent>>

    message_id: snowflakes.Snowflake = attr.field()
    # <<inherited docstring from MessageDeleteEvent>>

    old_message: typing.Optional[messages.Message] = attr.field()
    # <<inherited docstring from MessageDeleteEvent>>

    shard: shard_.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from ShardEvent>>


@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.GUILD_MESSAGES)
class GuildBulkMessageDeleteEvent(shard_events.ShardEvent):
    """Event that is triggered when a bulk deletion is triggered in a guild.

    .. note::
        Due to Discord limitations, most message information is unavailable
        during deletion events.
    """

    app: traits.RESTAware = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from Event>>

    channel_id: snowflakes.Snowflake = attr.field()
    """ID of the channel that this event concerns."""

    guild_id: snowflakes.Snowflake = attr.field()
    """ID of the guild that this event occurred in."""

    message_ids: typing.AbstractSet[snowflakes.Snowflake] = attr.field()
    """Set of message IDs that were bulk deleted."""

    old_messages: typing.Mapping[snowflakes.Snowflake, messages.Message] = attr.field()
    """Mapping of a snowflake to the deleted message object.

    If the message was not found in the cache it will be missing from the mapping.
    """

    shard: shard_.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from ShardEvent>>

    def get_channel(self) -> typing.Optional[channels.TextableGuildChannel]:
        """Get the cached channel the messages were sent in, if known.

        Returns
        -------
        typing.Optional[hikari.channels.TextableGuildChannel]
            The channel the messages were sent in, or `None` if not
            known/cached.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        channel = self.app.cache.get_guild_channel(self.channel_id)
        assert channel is None or isinstance(
            channel, channels.TextableGuildChannel
        ), f"Cached channel ID is not a TextableGuildChannel, but a {type(channel).__name__}!"
        return channel

    def get_guild(self) -> typing.Optional[guilds.GatewayGuild]:
        """Get the cached guild this event corresponds to, if known.

        .. note::
            You will need `hikari.intents.Intents.GUILDS` enabled to receive this
            information.

        Returns
        -------
        hikari.guilds.GatewayGuild
            The gateway guild that this event corresponds to, if known and
            cached.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        return self.app.cache.get_guild(self.guild_id)
#  
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.DM_MESSAGES)
class DMMessageCreateEvent(MessageCreateEvent):
View Source
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.DM_MESSAGES)
class DMMessageCreateEvent(MessageCreateEvent):
    """Event that is fired when a message is created within a DM.

    This contains the full message in the internal `message` attribute.
    """

    message: messages.Message = attr.field()
    # <<inherited docstring from MessageCreateEvent>>

    shard: shard_.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from ShardEvent>>

Event that is fired when a message is created within a DM.

This contains the full message in the internal message attribute.

This requires one of the following combinations of intents in order to be dispatched:

Variables and properties

App instance for this application.

User that sent the message.

ID of the author of the message this event concerns.

ID of the channel that this event concerns.

#  content: Optional[str]

Content of the message.

The content of the message, if present. This will be None if no content is present (e.g. if only an embed was sent).

#  embeds: Sequence[hikari.embeds.Embed]

Sequence of embeds in the message.

#  is_bot: bool

Return True if the message is from a bot.

#  is_human: bool

Return True if the message was created by a human.

#  is_webhook: bool

Return True if the message was created by a webhook.

ID of the message that this event concerns.

Methods
#  def __init__(
   self,
   *,
   message: hikari.messages.Message,
   shard: hikari.api.shard.GatewayShard
):
View Source
def __init__(self, *, message, shard):
    self.message = message
    self.shard = shard

Method generated by attrs for class DMMessageCreateEvent.

#  
@classmethod
def bitmask(cls) -> int:
View Source
    @classmethod
    def bitmask(cls) -> int:
        """Bitmask for this event."""
        return cls.__bitmask

Bitmask for this event.

#  
@classmethod
def dispatches(cls) -> Sequence[Type[hikari.events.base_events.Event]]:
View Source
    @classmethod
    def dispatches(cls) -> typing.Sequence[typing.Type[Event]]:
        """Sequence of the event classes this event is dispatched as."""
        return cls.__dispatches

Sequence of the event classes this event is dispatched as.

#  
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.DM_MESSAGES)
class DMMessageDeleteEvent(MessageDeleteEvent):
View Source
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.DM_MESSAGES)
class DMMessageDeleteEvent(MessageDeleteEvent):
    """Event that is triggered if a message is deleted in a DM.

    .. note::
        Due to Discord limitations, most message information is unavailable
        during deletion events.
    """

    app: traits.RESTAware = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from Event>>

    channel_id: snowflakes.Snowflake = attr.field()
    # <<inherited docstring from MessageEvent>>

    message_id: snowflakes.Snowflake = attr.field()
    # <<inherited docstring from MessageDeleteEvent>>

    old_message: typing.Optional[messages.Message] = attr.field()
    # <<inherited docstring from MessageDeleteEvent>>

    shard: shard_.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from ShardEvent>>

Event that is triggered if a message is deleted in a DM.

Note: Due to Discord limitations, most message information is unavailable during deletion events.

This requires one of the following combinations of intents in order to be dispatched:

Variables and properties
#  old_message: Optional[hikari.messages.Message]
Methods
#  def __init__(
   self,
   *,
   app: hikari.traits.RESTAware,
   channel_id: hikari.snowflakes.Snowflake,
   message_id: hikari.snowflakes.Snowflake,
   old_message: Optional[hikari.messages.Message],
   shard: hikari.api.shard.GatewayShard
):
View Source
def __init__(self, *, app, channel_id, message_id, old_message, shard):
    self.app = app
    self.channel_id = channel_id
    self.message_id = message_id
    self.old_message = old_message
    self.shard = shard

Method generated by attrs for class DMMessageDeleteEvent.

#  
@classmethod
def bitmask(cls) -> int:
View Source
    @classmethod
    def bitmask(cls) -> int:
        """Bitmask for this event."""
        return cls.__bitmask

Bitmask for this event.

#  
@classmethod
def dispatches(cls) -> Sequence[Type[hikari.events.base_events.Event]]:
View Source
    @classmethod
    def dispatches(cls) -> typing.Sequence[typing.Type[Event]]:
        """Sequence of the event classes this event is dispatched as."""
        return cls.__dispatches

Sequence of the event classes this event is dispatched as.

#  
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.DM_MESSAGES)
class DMMessageUpdateEvent(MessageUpdateEvent):
View Source
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.DM_MESSAGES)
class DMMessageUpdateEvent(MessageUpdateEvent):
    """Event that is fired when a message is updated in a DM.

    .. note::
        Less information will be available here than in the creation event
        due to Discord limitations.
    """

    old_message: typing.Optional[messages.PartialMessage] = attr.field()
    """The old message object.

    This will be `None` if the message missing from the cache.
    """

    message: messages.PartialMessage = attr.field()
    # <<inherited docstring from MessageUpdateEvent>>

    shard: shard_.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from ShardEvent>>

Event that is fired when a message is updated in a DM.

Note: Less information will be available here than in the creation event due to Discord limitations.

This requires one of the following combinations of intents in order to be dispatched:

Variables and properties

App instance for this application.

User that sent the message.

This will be hikari.undefined.UNDEFINED in some cases such as when Discord updates a message with an embed URL preview.

ID of the author that triggered this event.

This will be hikari.undefined.UNDEFINED in some cases such as when Discord updates a message with an embed URL preview.

ID of the channel that this event concerns.

#  content: Union[str, hikari.undefined.UndefinedType, NoneType]

Content of the message.

The content of the message, if present. This may be None if no content is present (e.g. if only an embed was sent).

If not part of the update, then this will be hikari.undefined.UNDEFINED instead.

Sequence of embeds in the message.

If the embeds were not changed in this event, then this may instead be hikari.undefined.UNDEFINED.

Whether the message is from a bot.

If the author is not known, due to the update event being caused by Discord adding an embed preview to accompany a URL, then this will return hikari.undefined.UNDEFINED instead.

Whether the message was created by a human.

If the author is not known, due to the update event being caused by Discord adding an embed preview to accompany a URL, then this may return hikari.undefined.UNDEFINED instead.

#  is_webhook: Union[bool, hikari.undefined.UndefinedType]

Whether the message was created by a webhook.

If the author is not known, due to the update event being caused by Discord adding an embed preview to accompany a URL, then this may return hikari.undefined.UNDEFINED instead.

ID of the message that this event concerns.

The old message object.

This will be None if the message missing from the cache.

Methods
#  def __init__(
   self,
   *,
   old_message: Optional[hikari.messages.PartialMessage],
   message: hikari.messages.PartialMessage,
   shard: hikari.api.shard.GatewayShard
):
View Source
def __init__(self, *, old_message, message, shard):
    self.old_message = old_message
    self.message = message
    self.shard = shard

Method generated by attrs for class DMMessageUpdateEvent.

#  
@classmethod
def bitmask(cls) -> int:
View Source
    @classmethod
    def bitmask(cls) -> int:
        """Bitmask for this event."""
        return cls.__bitmask

Bitmask for this event.

#  
@classmethod
def dispatches(cls) -> Sequence[Type[hikari.events.base_events.Event]]:
View Source
    @classmethod
    def dispatches(cls) -> typing.Sequence[typing.Type[Event]]:
        """Sequence of the event classes this event is dispatched as."""
        return cls.__dispatches

Sequence of the event classes this event is dispatched as.

#  
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.GUILD_MESSAGES)
class GuildBulkMessageDeleteEvent(hikari.events.shard_events.ShardEvent):
View Source
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.GUILD_MESSAGES)
class GuildBulkMessageDeleteEvent(shard_events.ShardEvent):
    """Event that is triggered when a bulk deletion is triggered in a guild.

    .. note::
        Due to Discord limitations, most message information is unavailable
        during deletion events.
    """

    app: traits.RESTAware = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from Event>>

    channel_id: snowflakes.Snowflake = attr.field()
    """ID of the channel that this event concerns."""

    guild_id: snowflakes.Snowflake = attr.field()
    """ID of the guild that this event occurred in."""

    message_ids: typing.AbstractSet[snowflakes.Snowflake] = attr.field()
    """Set of message IDs that were bulk deleted."""

    old_messages: typing.Mapping[snowflakes.Snowflake, messages.Message] = attr.field()
    """Mapping of a snowflake to the deleted message object.

    If the message was not found in the cache it will be missing from the mapping.
    """

    shard: shard_.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from ShardEvent>>

    def get_channel(self) -> typing.Optional[channels.TextableGuildChannel]:
        """Get the cached channel the messages were sent in, if known.

        Returns
        -------
        typing.Optional[hikari.channels.TextableGuildChannel]
            The channel the messages were sent in, or `None` if not
            known/cached.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        channel = self.app.cache.get_guild_channel(self.channel_id)
        assert channel is None or isinstance(
            channel, channels.TextableGuildChannel
        ), f"Cached channel ID is not a TextableGuildChannel, but a {type(channel).__name__}!"
        return channel

    def get_guild(self) -> typing.Optional[guilds.GatewayGuild]:
        """Get the cached guild this event corresponds to, if known.

        .. note::
            You will need `hikari.intents.Intents.GUILDS` enabled to receive this
            information.

        Returns
        -------
        hikari.guilds.GatewayGuild
            The gateway guild that this event corresponds to, if known and
            cached.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        return self.app.cache.get_guild(self.guild_id)

Event that is triggered when a bulk deletion is triggered in a guild.

Note: Due to Discord limitations, most message information is unavailable during deletion events.

This requires one of the following combinations of intents in order to be dispatched:

Variables and properties

ID of the channel that this event concerns.

ID of the guild that this event occurred in.

#  message_ids: AbstractSet[hikari.snowflakes.Snowflake]

Set of message IDs that were bulk deleted.

Mapping of a snowflake to the deleted message object.

If the message was not found in the cache it will be missing from the mapping.

Methods
#  def __init__(
   self,
   *,
   app: hikari.traits.RESTAware,
   channel_id: hikari.snowflakes.Snowflake,
   guild_id: hikari.snowflakes.Snowflake,
   message_ids: AbstractSet[hikari.snowflakes.Snowflake],
   old_messages: Mapping[hikari.snowflakes.Snowflake, hikari.messages.Message],
   shard: hikari.api.shard.GatewayShard
):
View Source
def __init__(self, *, app, channel_id, guild_id, message_ids, old_messages, shard):
    self.app = app
    self.channel_id = channel_id
    self.guild_id = guild_id
    self.message_ids = message_ids
    self.old_messages = old_messages
    self.shard = shard

Method generated by attrs for class GuildBulkMessageDeleteEvent.

#  
@classmethod
def bitmask(cls) -> int:
View Source
    @classmethod
    def bitmask(cls) -> int:
        """Bitmask for this event."""
        return cls.__bitmask

Bitmask for this event.

#  
@classmethod
def dispatches(cls) -> Sequence[Type[hikari.events.base_events.Event]]:
View Source
    @classmethod
    def dispatches(cls) -> typing.Sequence[typing.Type[Event]]:
        """Sequence of the event classes this event is dispatched as."""
        return cls.__dispatches

Sequence of the event classes this event is dispatched as.

#  def get_channel(self) -> Optional[hikari.channels.TextableGuildChannel]:
View Source
    def get_channel(self) -> typing.Optional[channels.TextableGuildChannel]:
        """Get the cached channel the messages were sent in, if known.

        Returns
        -------
        typing.Optional[hikari.channels.TextableGuildChannel]
            The channel the messages were sent in, or `None` if not
            known/cached.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        channel = self.app.cache.get_guild_channel(self.channel_id)
        assert channel is None or isinstance(
            channel, channels.TextableGuildChannel
        ), f"Cached channel ID is not a TextableGuildChannel, but a {type(channel).__name__}!"
        return channel

Get the cached channel the messages were sent in, if known.

Returns
#  def get_guild(self) -> Optional[hikari.guilds.GatewayGuild]:
View Source
    def get_guild(self) -> typing.Optional[guilds.GatewayGuild]:
        """Get the cached guild this event corresponds to, if known.

        .. note::
            You will need `hikari.intents.Intents.GUILDS` enabled to receive this
            information.

        Returns
        -------
        hikari.guilds.GatewayGuild
            The gateway guild that this event corresponds to, if known and
            cached.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        return self.app.cache.get_guild(self.guild_id)

Get the cached guild this event corresponds to, if known.

Note: You will need hikari.intents.Intents.GUILDS enabled to receive this information.

Returns
#  
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.GUILD_MESSAGES)
class GuildMessageCreateEvent(MessageCreateEvent):
View Source
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.GUILD_MESSAGES)
class GuildMessageCreateEvent(MessageCreateEvent):
    """Event that is fired when a message is created within a guild.

    This contains the full message in the internal `message` attribute.
    """

    message: messages.Message = attr.field()
    # <<inherited docstring from MessageCreateEvent>>

    shard: shard_.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from ShardEvent>>

    @property
    def author(self) -> users.User:
        """User object of the user that sent the message."""
        return self.message.author

    @property
    def member(self) -> typing.Optional[guilds.Member]:
        """Member object of the user that sent the message."""
        return self.message.member

    @property
    def guild_id(self) -> snowflakes.Snowflake:
        """ID of the guild that this event occurred in."""
        guild_id = self.message.guild_id
        # Always present on guild events
        assert isinstance(guild_id, snowflakes.Snowflake), "no guild_id attribute set"
        return guild_id

    def get_channel(self) -> typing.Optional[channels.TextableGuildChannel]:
        """Channel that the message was sent in, if known.

        Returns
        -------
        typing.Optional[hikari.channels.TextableGuildChannel]
            The channel that the message was sent in, if known and cached,
            otherwise, `None`.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        channel = self.app.cache.get_guild_channel(self.channel_id)
        assert channel is None or isinstance(
            channel, channels.TextableGuildChannel
        ), f"Cached channel ID is not a TextableGuildChannel, but a {type(channel).__name__}!"
        return channel

    def get_guild(self) -> typing.Optional[guilds.GatewayGuild]:
        """Get the cached guild that this event occurred in, if known.

        .. note::
            This will require the `GUILDS` intent to be specified on start-up
            in order to be known.

        Returns
        -------
        typing.Optional[hikari.guilds.GatewayGuild]
            The guild that this event occurred in, if cached. Otherwise,
            `None` instead.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        return self.app.cache.get_guild(self.guild_id)

    def get_member(self) -> typing.Optional[guilds.Member]:
        """Get the member that sent this message from the cache if available.

        Returns
        -------
        typing.Optional[hikari.guilds.Member]
            Cached object of the member that sent the message if found.
        """
        if isinstance(self.app, traits.CacheAware):
            return self.app.cache.get_member(self.guild_id, self.message.author.id)

        return None

Event that is fired when a message is created within a guild.

This contains the full message in the internal message attribute.

This requires one of the following combinations of intents in order to be dispatched:

Variables and properties

App instance for this application.

User object of the user that sent the message.

ID of the author of the message this event concerns.

ID of the channel that this event concerns.

#  content: Optional[str]

Content of the message.

The content of the message, if present. This will be None if no content is present (e.g. if only an embed was sent).

#  embeds: Sequence[hikari.embeds.Embed]

Sequence of embeds in the message.

ID of the guild that this event occurred in.

#  is_bot: bool

Return True if the message is from a bot.

#  is_human: bool

Return True if the message was created by a human.

#  is_webhook: bool

Return True if the message was created by a webhook.

#  member: Optional[hikari.guilds.Member]

Member object of the user that sent the message.

ID of the message that this event concerns.

Methods
#  def __init__(
   self,
   *,
   message: hikari.messages.Message,
   shard: hikari.api.shard.GatewayShard
):
View Source
def __init__(self, *, message, shard):
    self.message = message
    self.shard = shard

Method generated by attrs for class GuildMessageCreateEvent.

#  
@classmethod
def bitmask(cls) -> int:
View Source
    @classmethod
    def bitmask(cls) -> int:
        """Bitmask for this event."""
        return cls.__bitmask

Bitmask for this event.

#  
@classmethod
def dispatches(cls) -> Sequence[Type[hikari.events.base_events.Event]]:
View Source
    @classmethod
    def dispatches(cls) -> typing.Sequence[typing.Type[Event]]:
        """Sequence of the event classes this event is dispatched as."""
        return cls.__dispatches

Sequence of the event classes this event is dispatched as.

#  def get_channel(self) -> Optional[hikari.channels.TextableGuildChannel]:
View Source
    def get_channel(self) -> typing.Optional[channels.TextableGuildChannel]:
        """Channel that the message was sent in, if known.

        Returns
        -------
        typing.Optional[hikari.channels.TextableGuildChannel]
            The channel that the message was sent in, if known and cached,
            otherwise, `None`.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        channel = self.app.cache.get_guild_channel(self.channel_id)
        assert channel is None or isinstance(
            channel, channels.TextableGuildChannel
        ), f"Cached channel ID is not a TextableGuildChannel, but a {type(channel).__name__}!"
        return channel

Channel that the message was sent in, if known.

Returns
#  def get_guild(self) -> Optional[hikari.guilds.GatewayGuild]:
View Source
    def get_guild(self) -> typing.Optional[guilds.GatewayGuild]:
        """Get the cached guild that this event occurred in, if known.

        .. note::
            This will require the `GUILDS` intent to be specified on start-up
            in order to be known.

        Returns
        -------
        typing.Optional[hikari.guilds.GatewayGuild]
            The guild that this event occurred in, if cached. Otherwise,
            `None` instead.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        return self.app.cache.get_guild(self.guild_id)

Get the cached guild that this event occurred in, if known.

Note: This will require the GUILDS intent to be specified on start-up in order to be known.

Returns
#  def get_member(self) -> Optional[hikari.guilds.Member]:
View Source
    def get_member(self) -> typing.Optional[guilds.Member]:
        """Get the member that sent this message from the cache if available.

        Returns
        -------
        typing.Optional[hikari.guilds.Member]
            Cached object of the member that sent the message if found.
        """
        if isinstance(self.app, traits.CacheAware):
            return self.app.cache.get_member(self.guild_id, self.message.author.id)

        return None

Get the member that sent this message from the cache if available.

Returns
#  
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.GUILD_MESSAGES)
class GuildMessageDeleteEvent(MessageDeleteEvent):
View Source
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.GUILD_MESSAGES)
class GuildMessageDeleteEvent(MessageDeleteEvent):
    """Event that is triggered if a message is deleted in a guild.

    .. note::
        Due to Discord limitations, most message information is unavailable
        during deletion events.
    """

    app: traits.RESTAware = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from Event>>

    channel_id: snowflakes.Snowflake = attr.field()
    # <<inherited docstring from MessageEvent>>

    guild_id: snowflakes.Snowflake = attr.field()
    """ID of the guild that this event occurred in."""

    message_id: snowflakes.Snowflake = attr.field()
    # <<inherited docstring from MessageDeleteEvent>>

    old_message: typing.Optional[messages.Message] = attr.field()
    # <<inherited docstring from MessageDeleteEvent>>

    shard: shard_.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from ShardEvent>>

    def get_channel(self) -> typing.Optional[channels.TextableGuildChannel]:
        """Get the cached channel the message were sent in, if known.

        Returns
        -------
        typing.Optional[hikari.channels.TextableGuildChannel]
            The channel the messages were sent in, or `None` if not
            known/cached.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        channel = self.app.cache.get_guild_channel(self.channel_id)
        assert channel is None or isinstance(
            channel, channels.TextableGuildChannel
        ), f"Cached channel ID is not a TextableGuildChannel, but a {type(channel).__name__}!"
        return channel

    def get_guild(self) -> typing.Optional[guilds.GatewayGuild]:
        """Get the cached guild this event corresponds to, if known.

        .. note::
            You will need `hikari.intents.Intents.GUILDS` enabled to receive this
            information.

        Returns
        -------
        hikari.guilds.GatewayGuild
            The gateway guild that this event corresponds to, if known and
            cached.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        return self.app.cache.get_guild(self.guild_id)

Event that is triggered if a message is deleted in a guild.

Note: Due to Discord limitations, most message information is unavailable during deletion events.

This requires one of the following combinations of intents in order to be dispatched:

Variables and properties

ID of the guild that this event occurred in.

#  old_message: Optional[hikari.messages.Message]
Methods
#  def __init__(
   self,
   *,
   app: hikari.traits.RESTAware,
   channel_id: hikari.snowflakes.Snowflake,
   guild_id: hikari.snowflakes.Snowflake,
   message_id: hikari.snowflakes.Snowflake,
   old_message: Optional[hikari.messages.Message],
   shard: hikari.api.shard.GatewayShard
):
View Source
def __init__(self, *, app, channel_id, guild_id, message_id, old_message, shard):
    self.app = app
    self.channel_id = channel_id
    self.guild_id = guild_id
    self.message_id = message_id
    self.old_message = old_message
    self.shard = shard

Method generated by attrs for class GuildMessageDeleteEvent.

#  
@classmethod
def bitmask(cls) -> int:
View Source
    @classmethod
    def bitmask(cls) -> int:
        """Bitmask for this event."""
        return cls.__bitmask

Bitmask for this event.

#  
@classmethod
def dispatches(cls) -> Sequence[Type[hikari.events.base_events.Event]]:
View Source
    @classmethod
    def dispatches(cls) -> typing.Sequence[typing.Type[Event]]:
        """Sequence of the event classes this event is dispatched as."""
        return cls.__dispatches

Sequence of the event classes this event is dispatched as.

#  def get_channel(self) -> Optional[hikari.channels.TextableGuildChannel]:
View Source
    def get_channel(self) -> typing.Optional[channels.TextableGuildChannel]:
        """Get the cached channel the message were sent in, if known.

        Returns
        -------
        typing.Optional[hikari.channels.TextableGuildChannel]
            The channel the messages were sent in, or `None` if not
            known/cached.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        channel = self.app.cache.get_guild_channel(self.channel_id)
        assert channel is None or isinstance(
            channel, channels.TextableGuildChannel
        ), f"Cached channel ID is not a TextableGuildChannel, but a {type(channel).__name__}!"
        return channel

Get the cached channel the message were sent in, if known.

Returns
#  def get_guild(self) -> Optional[hikari.guilds.GatewayGuild]:
View Source
    def get_guild(self) -> typing.Optional[guilds.GatewayGuild]:
        """Get the cached guild this event corresponds to, if known.

        .. note::
            You will need `hikari.intents.Intents.GUILDS` enabled to receive this
            information.

        Returns
        -------
        hikari.guilds.GatewayGuild
            The gateway guild that this event corresponds to, if known and
            cached.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        return self.app.cache.get_guild(self.guild_id)

Get the cached guild this event corresponds to, if known.

Note: You will need hikari.intents.Intents.GUILDS enabled to receive this information.

Returns
#  
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.GUILD_MESSAGES)
class GuildMessageUpdateEvent(MessageUpdateEvent):
View Source
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
@base_events.requires_intents(intents.Intents.GUILD_MESSAGES)
class GuildMessageUpdateEvent(MessageUpdateEvent):
    """Event that is fired when a message is updated in a guild.

    .. note::
        Less information will be available here than in the creation event
        due to Discord limitations.
    """

    old_message: typing.Optional[messages.PartialMessage] = attr.field()
    """The old message object.

    This will be `None` if the message missing from the cache.
    """

    message: messages.PartialMessage = attr.field()
    # <<inherited docstring from MessageUpdateEvent>>

    shard: shard_.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    # <<inherited docstring from ShardEvent>>

    @property
    def member(self) -> undefined.UndefinedNoneOr[guilds.Member]:
        """Member that sent the message if provided by the event.

        If the message is not in a guild, this will be `None`.

        This will also be `hikari.undefined.UNDEFINED` in some cases such as when Discord
        updates a message with an embed URL preview.
        """
        return self.message.member

    def get_member(self) -> typing.Optional[guilds.Member]:
        """Get the member that sent this message from the cache if available.

        Returns
        -------
        typing.Optional[hikari.guilds.Member]
            Cached object of the member that sent the message if found.
        """
        if self.message.author is not undefined.UNDEFINED and isinstance(self.app, traits.CacheAware):
            return self.app.cache.get_member(self.guild_id, self.message.author.id)

        return None

    @property
    def guild_id(self) -> snowflakes.Snowflake:
        """ID of the guild that this event occurred in."""
        guild_id = self.message.guild_id
        # Always present on guild events
        assert isinstance(guild_id, snowflakes.Snowflake), f"expected guild_id, got {guild_id}"
        return guild_id

    def get_channel(self) -> typing.Optional[channels.TextableGuildChannel]:
        """Channel that the message was sent in, if known.

        Returns
        -------
        typing.Optional[hikari.channels.TextableGuildChannel]
            The channel that the message was sent in, if known and cached,
            otherwise, `None`.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        channel = self.app.cache.get_guild_channel(self.channel_id)
        assert channel is None or isinstance(
            channel, channels.TextableGuildChannel
        ), f"Cached channel ID is not a TextableGuildChannel, but a {type(channel).__name__}!"
        return channel

    def get_guild(self) -> typing.Optional[guilds.GatewayGuild]:
        """Get the cached guild that this event occurred in, if known.

        .. note::
            This will require the `GUILDS` intent to be specified on start-up
            in order to be known.

        Returns
        -------
        typing.Optional[hikari.guilds.GatewayGuild]
            The guild that this event occurred in, if cached. Otherwise,
            `None` instead.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        return self.app.cache.get_guild(self.guild_id)

Event that is fired when a message is updated in a guild.

Note: Less information will be available here than in the creation event due to Discord limitations.

This requires one of the following combinations of intents in order to be dispatched:

Variables and properties

App instance for this application.

User that sent the message.

This will be hikari.undefined.UNDEFINED in some cases such as when Discord updates a message with an embed URL preview.

ID of the author that triggered this event.

This will be hikari.undefined.UNDEFINED in some cases such as when Discord updates a message with an embed URL preview.

ID of the channel that this event concerns.

#  content: Union[str, hikari.undefined.UndefinedType, NoneType]

Content of the message.

The content of the message, if present. This may be None if no content is present (e.g. if only an embed was sent).

If not part of the update, then this will be hikari.undefined.UNDEFINED instead.

Sequence of embeds in the message.

If the embeds were not changed in this event, then this may instead be hikari.undefined.UNDEFINED.

ID of the guild that this event occurred in.

Whether the message is from a bot.

If the author is not known, due to the update event being caused by Discord adding an embed preview to accompany a URL, then this will return hikari.undefined.UNDEFINED instead.

Whether the message was created by a human.

If the author is not known, due to the update event being caused by Discord adding an embed preview to accompany a URL, then this may return hikari.undefined.UNDEFINED instead.

#  is_webhook: Union[bool, hikari.undefined.UndefinedType]

Whether the message was created by a webhook.

If the author is not known, due to the update event being caused by Discord adding an embed preview to accompany a URL, then this may return hikari.undefined.UNDEFINED instead.

Member that sent the message if provided by the event.

If the message is not in a guild, this will be None.

This will also be hikari.undefined.UNDEFINED in some cases such as when Discord updates a message with an embed URL preview.

ID of the message that this event concerns.

The old message object.

This will be None if the message missing from the cache.

Methods
#  def __init__(
   self,
   *,
   old_message: Optional[hikari.messages.PartialMessage],
   message: hikari.messages.PartialMessage,
   shard: hikari.api.shard.GatewayShard
):
View Source
def __init__(self, *, old_message, message, shard):
    self.old_message = old_message
    self.message = message
    self.shard = shard

Method generated by attrs for class GuildMessageUpdateEvent.

#  
@classmethod
def bitmask(cls) -> int:
View Source
    @classmethod
    def bitmask(cls) -> int:
        """Bitmask for this event."""
        return cls.__bitmask

Bitmask for this event.

#  
@classmethod
def dispatches(cls) -> Sequence[Type[hikari.events.base_events.Event]]:
View Source
    @classmethod
    def dispatches(cls) -> typing.Sequence[typing.Type[Event]]:
        """Sequence of the event classes this event is dispatched as."""
        return cls.__dispatches

Sequence of the event classes this event is dispatched as.

#  def get_channel(self) -> Optional[hikari.channels.TextableGuildChannel]:
View Source
    def get_channel(self) -> typing.Optional[channels.TextableGuildChannel]:
        """Channel that the message was sent in, if known.

        Returns
        -------
        typing.Optional[hikari.channels.TextableGuildChannel]
            The channel that the message was sent in, if known and cached,
            otherwise, `None`.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        channel = self.app.cache.get_guild_channel(self.channel_id)
        assert channel is None or isinstance(
            channel, channels.TextableGuildChannel
        ), f"Cached channel ID is not a TextableGuildChannel, but a {type(channel).__name__}!"
        return channel

Channel that the message was sent in, if known.

Returns
#  def get_guild(self) -> Optional[hikari.guilds.GatewayGuild]:
View Source
    def get_guild(self) -> typing.Optional[guilds.GatewayGuild]:
        """Get the cached guild that this event occurred in, if known.

        .. note::
            This will require the `GUILDS` intent to be specified on start-up
            in order to be known.

        Returns
        -------
        typing.Optional[hikari.guilds.GatewayGuild]
            The guild that this event occurred in, if cached. Otherwise,
            `None` instead.
        """
        if not isinstance(self.app, traits.CacheAware):
            return None

        return self.app.cache.get_guild(self.guild_id)

Get the cached guild that this event occurred in, if known.

Note: This will require the GUILDS intent to be specified on start-up in order to be known.

Returns
#  def get_member(self) -> Optional[hikari.guilds.Member]:
View Source
    def get_member(self) -> typing.Optional[guilds.Member]:
        """Get the member that sent this message from the cache if available.

        Returns
        -------
        typing.Optional[hikari.guilds.Member]
            Cached object of the member that sent the message if found.
        """
        if self.message.author is not undefined.UNDEFINED and isinstance(self.app, traits.CacheAware):
            return self.app.cache.get_member(self.guild_id, self.message.author.id)

        return None

Get the member that sent this message from the cache if available.

Returns
#  
@base_events.requires_intents(intents.Intents.DM_MESSAGES, intents.Intents.GUILD_MESSAGES)
class MessageCreateEvent(MessageEvent, abc.ABC):
View Source
@base_events.requires_intents(intents.Intents.DM_MESSAGES, intents.Intents.GUILD_MESSAGES)
class MessageCreateEvent(MessageEvent, abc.ABC):
    """Event that is fired when a message is created."""

    __slots__: typing.Sequence[str] = ()

    @property
    def app(self) -> traits.RESTAware:
        # <<inherited docstring from Event>>.
        return self.message.app

    @property
    def author(self) -> users.User:
        """User that sent the message."""
        return self.message.author

    @property
    def author_id(self) -> snowflakes.Snowflake:
        """ID of the author of the message this event concerns."""
        return self.author.id

    @property
    def channel_id(self) -> snowflakes.Snowflake:
        # <<inherited docstring from MessageEvent>>
        return self.message.channel_id

    @property
    def content(self) -> typing.Optional[str]:
        """Content of the message.

        The content of the message, if present. This will be `None`
        if no content is present (e.g. if only an embed was sent).
        """
        return self.message.content

    @property
    def embeds(self) -> typing.Sequence[embeds_.Embed]:
        """Sequence of embeds in the message."""
        return self.message.embeds

    @property
    def is_bot(self) -> bool:
        """Return `True` if the message is from a bot."""
        return self.message.author.is_bot

    @property
    def is_human(self) -> bool:
        """Return `True` if the message was created by a human."""
        # Not second-guessing some weird edge case will occur in the future with this,
        # so I am being safe rather than sorry.
        return not self.message.author.is_bot and self.message.webhook_id is None

    @property
    def is_webhook(self) -> bool:
        """Return `True` if the message was created by a webhook."""
        return self.message.webhook_id is not None

    @property
    @abc.abstractmethod
    def message(self) -> messages.Message:
        """Message that was sent in the event."""

    @property
    def message_id(self) -> snowflakes.Snowflake:
        """ID of the message that this event concerns."""
        return self.message.id

Event that is fired when a message is created.

This requires one of the following combinations of intents in order to be dispatched:

Variables and properties

App instance for this application.

User that sent the message.

ID of the author of the message this event concerns.

ID of the channel that this event concerns.

#  content: Optional[str]

Content of the message.

The content of the message, if present. This will be None if no content is present (e.g. if only an embed was sent).

#  embeds: Sequence[hikari.embeds.Embed]

Sequence of embeds in the message.

#  is_bot: bool

Return True if the message is from a bot.

#  is_human: bool

Return True if the message was created by a human.

#  is_webhook: bool

Return True if the message was created by a webhook.

Message that was sent in the event.

ID of the message that this event concerns.

Shard that received this event.

Methods
#  
@classmethod
def bitmask(cls) -> int:
View Source
    @classmethod
    def bitmask(cls) -> int:
        """Bitmask for this event."""
        return cls.__bitmask

Bitmask for this event.

#  
@classmethod
def dispatches(cls) -> Sequence[Type[hikari.events.base_events.Event]]:
View Source
    @classmethod
    def dispatches(cls) -> typing.Sequence[typing.Type[Event]]:
        """Sequence of the event classes this event is dispatched as."""
        return cls.__dispatches

Sequence of the event classes this event is dispatched as.

#  
@base_events.requires_intents(intents.Intents.GUILD_MESSAGES, intents.Intents.DM_MESSAGES)
class MessageDeleteEvent(MessageEvent, abc.ABC):
View Source
@base_events.requires_intents(intents.Intents.GUILD_MESSAGES, intents.Intents.DM_MESSAGES)
class MessageDeleteEvent(MessageEvent, abc.ABC):
    """Special event that is triggered when a message gets deleted.

    .. note::
        Due to Discord limitations, most message information is unavailable
        during deletion events.
    """

    __slots__: typing.Sequence[str] = ()

    @property
    @abc.abstractmethod
    def message_id(self) -> snowflakes.Snowflake:
        """ID of the message that was deleted."""

    @property
    @abc.abstractmethod
    def old_message(self) -> typing.Optional[messages.Message]:
        """Object of the message that was deleted.

        Will be `None` if the message was not found in the cache.
        """

Special event that is triggered when a message gets deleted.

Note: Due to Discord limitations, most message information is unavailable during deletion events.

This requires one of the following combinations of intents in order to be dispatched:

Variables and properties

App instance for this application.

ID of the channel that this event concerns.

ID of the message that was deleted.

#  old_message: Optional[hikari.messages.Message]

Object of the message that was deleted.

Will be None if the message was not found in the cache.

Shard that received this event.

Methods
#  
@classmethod
def bitmask(cls) -> int:
View Source
    @classmethod
    def bitmask(cls) -> int:
        """Bitmask for this event."""
        return cls.__bitmask

Bitmask for this event.

#  
@classmethod
def dispatches(cls) -> Sequence[Type[hikari.events.base_events.Event]]:
View Source
    @classmethod
    def dispatches(cls) -> typing.Sequence[typing.Type[Event]]:
        """Sequence of the event classes this event is dispatched as."""
        return cls.__dispatches

Sequence of the event classes this event is dispatched as.

#  
@base_events.requires_intents(intents.Intents.DM_MESSAGES, intents.Intents.GUILD_MESSAGES)
class MessageEvent(hikari.events.shard_events.ShardEvent, abc.ABC):
View Source
@base_events.requires_intents(intents.Intents.DM_MESSAGES, intents.Intents.GUILD_MESSAGES)
class MessageEvent(shard_events.ShardEvent, abc.ABC):
    """Any event that concerns manipulation of messages."""

    __slots__: typing.Sequence[str] = ()

    @property
    @abc.abstractmethod
    def channel_id(self) -> snowflakes.Snowflake:
        """ID of the channel that this event concerns."""

    @property
    @abc.abstractmethod
    def message_id(self) -> snowflakes.Snowflake:
        """ID of the message that this event concerns."""

Any event that concerns manipulation of messages.

This requires one of the following combinations of intents in order to be dispatched:

Variables and properties

App instance for this application.

ID of the channel that this event concerns.

ID of the message that this event concerns.

Shard that received this event.

Methods
#  
@classmethod
def bitmask(cls) -> int:
View Source
    @classmethod
    def bitmask(cls) -> int:
        """Bitmask for this event."""
        return cls.__bitmask

Bitmask for this event.

#  
@classmethod
def dispatches(cls) -> Sequence[Type[hikari.events.base_events.Event]]:
View Source
    @classmethod
    def dispatches(cls) -> typing.Sequence[typing.Type[Event]]:
        """Sequence of the event classes this event is dispatched as."""
        return cls.__dispatches

Sequence of the event classes this event is dispatched as.

#  
@base_events.requires_intents(intents.Intents.DM_MESSAGES, intents.Intents.GUILD_MESSAGES)
class MessageUpdateEvent(MessageEvent, abc.ABC):
View Source
@base_events.requires_intents(intents.Intents.DM_MESSAGES, intents.Intents.GUILD_MESSAGES)
class MessageUpdateEvent(MessageEvent, abc.ABC):
    """Event that is fired when a message is updated.

    .. note::
        Less information will be available here than in the creation event
        due to Discord limitations.
    """

    __slots__: typing.Sequence[str] = ()

    @property
    def app(self) -> traits.RESTAware:
        # <<inherited docstring from Event>>.
        return self.message.app

    @property
    def author(self) -> undefined.UndefinedOr[users.User]:
        """User that sent the message.

        This will be `hikari.undefined.UNDEFINED` in some cases such as when Discord
        updates a message with an embed URL preview.
        """
        return self.message.author

    @property
    def author_id(self) -> undefined.UndefinedOr[snowflakes.Snowflake]:
        """ID of the author that triggered this event.

        This will be `hikari.undefined.UNDEFINED` in some cases such as when Discord
        updates a message with an embed URL preview.
        """
        author = self.message.author
        return author.id if author is not undefined.UNDEFINED else undefined.UNDEFINED

    @property
    def channel_id(self) -> snowflakes.Snowflake:
        # <<inherited docstring from MessageEvent>>.
        return self.message.channel_id

    @property
    def content(self) -> undefined.UndefinedNoneOr[str]:
        """Content of the message.

        The content of the message, if present. This may be `None`
        if no content is present (e.g. if only an embed was sent).

        If not part of the update, then this will be
        `hikari.undefined.UNDEFINED` instead.
        """
        return self.message.content

    @property
    def embeds(self) -> undefined.UndefinedOr[typing.Sequence[embeds_.Embed]]:
        """Sequence of embeds in the message.

        If the embeds were not changed in this event, then this may instead be
        `hikari.undefined.UNDEFINED`.
        """
        return self.message.embeds

    @property
    def is_bot(self) -> undefined.UndefinedOr[bool]:
        """Whether the message is from a bot.

        If the author is not known, due to the update event being caused
        by Discord adding an embed preview to accompany a URL, then this
        will return `hikari.undefined.UNDEFINED` instead.
        """
        if (author := self.message.author) is not undefined.UNDEFINED:
            return author.is_bot

        return undefined.UNDEFINED

    @property
    def is_human(self) -> undefined.UndefinedOr[bool]:
        """Whether the message was created by a human.

        If the author is not known, due to the update event being caused
        by Discord adding an embed preview to accompany a URL, then this
        may return `hikari.undefined.UNDEFINED` instead.
        """
        # Not second-guessing some weird edge case will occur in the future with this,
        # so I am being safe rather than sorry.
        if (webhook_id := self.message.webhook_id) is not undefined.UNDEFINED:
            return webhook_id is None

        if (author := self.message.author) is not undefined.UNDEFINED:
            return not author.is_bot

        return undefined.UNDEFINED

    @property
    def is_webhook(self) -> undefined.UndefinedOr[bool]:
        """Whether the message was created by a webhook.

        If the author is not known, due to the update event being caused
        by Discord adding an embed preview to accompany a URL, then this
        may return `hikari.undefined.UNDEFINED` instead.
        """
        if (webhook_id := self.message.webhook_id) is not undefined.UNDEFINED:
            return webhook_id is not None

        return undefined.UNDEFINED

    @property
    @abc.abstractmethod
    def message(self) -> messages.PartialMessage:
        """Partial message that was sent in the event."""

    @property
    def message_id(self) -> snowflakes.Snowflake:
        """ID of the message that this event concerns."""
        return self.message.id

Event that is fired when a message is updated.

Note: Less information will be available here than in the creation event due to Discord limitations.

This requires one of the following combinations of intents in order to be dispatched:

Variables and properties

App instance for this application.

User that sent the message.

This will be hikari.undefined.UNDEFINED in some cases such as when Discord updates a message with an embed URL preview.

ID of the author that triggered this event.

This will be hikari.undefined.UNDEFINED in some cases such as when Discord updates a message with an embed URL preview.

ID of the channel that this event concerns.

#  content: Union[str, hikari.undefined.UndefinedType, NoneType]

Content of the message.

The content of the message, if present. This may be None if no content is present (e.g. if only an embed was sent).

If not part of the update, then this will be hikari.undefined.UNDEFINED instead.

Sequence of embeds in the message.

If the embeds were not changed in this event, then this may instead be hikari.undefined.UNDEFINED.

Whether the message is from a bot.

If the author is not known, due to the update event being caused by Discord adding an embed preview to accompany a URL, then this will return hikari.undefined.UNDEFINED instead.

Whether the message was created by a human.

If the author is not known, due to the update event being caused by Discord adding an embed preview to accompany a URL, then this may return hikari.undefined.UNDEFINED instead.

#  is_webhook: Union[bool, hikari.undefined.UndefinedType]

Whether the message was created by a webhook.

If the author is not known, due to the update event being caused by Discord adding an embed preview to accompany a URL, then this may return hikari.undefined.UNDEFINED instead.

Partial message that was sent in the event.

ID of the message that this event concerns.

Shard that received this event.

Methods
#  
@classmethod
def bitmask(cls) -> int:
View Source
    @classmethod
    def bitmask(cls) -> int:
        """Bitmask for this event."""
        return cls.__bitmask

Bitmask for this event.

#  
@classmethod
def dispatches(cls) -> Sequence[Type[hikari.events.base_events.Event]]:
View Source
    @classmethod
    def dispatches(cls) -> typing.Sequence[typing.Type[Event]]:
        """Sequence of the event classes this event is dispatched as."""
        return cls.__dispatches

Sequence of the event classes this event is dispatched as.