Back to top

hikari.impl.special_endpoints

Special endpoint implementations.

You should never need to make any of these objects manually.

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.
"""Special endpoint implementations.

You should never need to make any of these objects manually.
"""
from __future__ import annotations

__all__: typing.Sequence[str] = (
    "ActionRowBuilder",
    "CommandBuilder",
    "SlashCommandBuilder",
    "ContextMenuCommandBuilder",
    "TypingIndicator",
    "GuildBuilder",
    "InteractionAutocompleteBuilder",
    "InteractionDeferredBuilder",
    "InteractionMessageBuilder",
    "InteractiveButtonBuilder",
    "LinkButtonBuilder",
    "SelectMenuBuilder",
)

import asyncio
import typing

import attr

from hikari import channels
from hikari import commands
from hikari import emojis
from hikari import errors
from hikari import files
from hikari import iterators
from hikari import messages
from hikari import snowflakes
from hikari import undefined
from hikari.api import special_endpoints
from hikari.interactions import base_interactions
from hikari.internal import attr_extensions
from hikari.internal import data_binding
from hikari.internal import mentions
from hikari.internal import routes
from hikari.internal import time

if typing.TYPE_CHECKING:
    import concurrent.futures
    import types

    from hikari import applications
    from hikari import audit_logs
    from hikari import colors
    from hikari import embeds as embeds_
    from hikari import guilds
    from hikari import permissions as permissions_
    from hikari import scheduled_events
    from hikari import users
    from hikari import voices
    from hikari.api import entity_factory as entity_factory_
    from hikari.api import rest as rest_api

    _T = typing.TypeVar("_T")
    _CommandBuilderT = typing.TypeVar("_CommandBuilderT", bound="CommandBuilder")
    _SlashCommandBuilderT = typing.TypeVar("_SlashCommandBuilderT", bound="SlashCommandBuilder")
    _InteractionMessageBuilderT = typing.TypeVar("_InteractionMessageBuilderT", bound="InteractionMessageBuilder")
    _InteractionDeferredBuilderT = typing.TypeVar("_InteractionDeferredBuilderT", bound="InteractionDeferredBuilder")
    _InteractionAutocompleteBuilderT = typing.TypeVar(
        "_InteractionAutocompleteBuilderT", bound="InteractionAutocompleteBuilder"
    )
    _ActionRowBuilderT = typing.TypeVar("_ActionRowBuilderT", bound="ActionRowBuilder")
    _ButtonBuilderT = typing.TypeVar("_ButtonBuilderT", bound="_ButtonBuilder[typing.Any]")
    _SelectOptionBuilderT = typing.TypeVar("_SelectOptionBuilderT", bound="_SelectOptionBuilder[typing.Any]")
    _SelectMenuBuilderT = typing.TypeVar("_SelectMenuBuilderT", bound="SelectMenuBuilder[typing.Any]")

    # Hack around used to avoid recursive generic types leading to type checker issues in builders
    class _ContainerProto(typing.Protocol):
        def add_component(self: _T, component: special_endpoints.ComponentBuilder, /) -> _T:
            raise NotImplementedError


_ContainerProtoT = typing.TypeVar("_ContainerProtoT", bound="_ContainerProto")


@typing.final
class TypingIndicator(special_endpoints.TypingIndicator):
    """Result type of `hikari.api.rest.RESTClient.trigger_typing`.

    This is an object that can either be awaited like a coroutine to trigger
    the typing indicator once, or an async context manager to keep triggering
    the typing indicator repeatedly until the context finishes.

    .. note::
        This is a helper class that is used by `hikari.api.rest.RESTClient`.
        You should only ever need to use instances of this class that are
        produced by that API.
    """

    __slots__: typing.Sequence[str] = ("_route", "_request_call", "_task", "_rest_close_event", "_task_name")

    def __init__(
        self,
        request_call: typing.Callable[
            ..., typing.Coroutine[None, None, typing.Union[None, data_binding.JSONObject, data_binding.JSONArray]]
        ],
        channel: snowflakes.SnowflakeishOr[channels.TextableChannel],
        rest_closed_event: asyncio.Event,
    ) -> None:
        self._route = routes.POST_CHANNEL_TYPING.compile(channel=channel)
        self._request_call = request_call
        self._task_name = f"repeatedly trigger typing in {channel}"
        self._task: typing.Optional[asyncio.Task[None]] = None
        self._rest_close_event = rest_closed_event

    def __await__(self) -> typing.Generator[typing.Any, typing.Any, typing.Any]:
        return self._request_call(self._route).__await__()

    async def __aenter__(self) -> None:
        if self._task is not None:
            raise TypeError("Cannot enter a typing indicator context more than once")
        self._task = asyncio.create_task(self._keep_typing(), name=self._task_name)

    async def __aexit__(
        self,
        exc_type: typing.Optional[typing.Type[BaseException]],
        exc_val: typing.Optional[BaseException],
        exc_tb: typing.Optional[types.TracebackType],
    ) -> None:
        # This will always be true, but this keeps MyPy quiet.
        if self._task is not None:
            self._task.cancel()

    # These are only included at runtime in-order to avoid the model being typed as a synchronous context manager.
    if not typing.TYPE_CHECKING:

        def __enter__(self) -> typing.NoReturn:
            # This is async only.
            cls = type(self)
            raise TypeError(f"{cls.__module__}.{cls.__qualname__} is async-only, did you mean 'async with'?") from None

        def __exit__(
            self,
            exc_type: typing.Optional[typing.Type[Exception]],
            exc_val: typing.Optional[Exception],
            exc_tb: typing.Optional[types.TracebackType],
        ) -> None:
            return None

    async def _keep_typing(self) -> None:
        # Cancelled error will occur when the context manager is requested to
        # stop.
        try:
            # If the REST API closes while typing, just stop.
            while not self._rest_close_event.is_set():
                # Use slightly less than 10s to ensure latency does not
                # cause the typing indicator to stop showing for a split
                # second if the request is slow to execute.
                try:
                    await asyncio.gather(self, asyncio.wait_for(self._rest_close_event.wait(), timeout=9.0))
                except asyncio.TimeoutError:
                    pass

        except (asyncio.CancelledError, errors.ComponentStateConflictError):
            pass


# As a note, slotting allows us to override the settable properties while staying within the interface's spec.
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
class GuildBuilder(special_endpoints.GuildBuilder):
    """Result type of `hikari.api.rest.RESTClient.guild_builder`.

    This is used to create a guild in a tidy way using the HTTP API, since
    the logic behind creating a guild on an API level is somewhat confusing
    and detailed.

    .. note::
        This is a helper class that is used by `hikari.api.rest.RESTClient`.
        You should only ever need to use instances of this class that are
        produced by that API, thus, any details about the constructor are
        omitted from the following examples for brevity.

    Examples
    --------
    Creating an empty guild.

    ```py
    guild = await rest.guild_builder("My Server!").create()
    ```

    Creating a guild with an icon

    ```py
    from hikari.files import WebResourceStream

    guild_builder = rest.guild_builder("My Server!")
    guild_builder.icon = WebResourceStream("cat.png", "http://...")
    guild = await guild_builder.create()
    ```

    Adding roles to your guild.

    ```py
    from hikari.permissions import Permissions

    guild_builder = rest.guild_builder("My Server!")

    everyone_role_id = guild_builder.add_role("@everyone")
    admin_role_id = guild_builder.add_role("Admins", permissions=Permissions.ADMINISTRATOR)

    await guild_builder.create()
    ```

    .. warning::
        The first role must always be the `@everyone` role.

    .. note::
        If you call `add_role`, the default roles provided by Discord will
        be created. This also applies to the `add_` functions for
        text channels/voice channels/categories.

    .. note::
        Functions that return a `hikari.snowflakes.Snowflake` do
        **not** provide the final ID that the object will have once the
        API call is made. The returned IDs are only able to be used to
        re-reference particular objects while building the guild format.

        This is provided to allow creation of channels within categories,
        and to provide permission overwrites.

    Adding a text channel to your guild.

    ```py
    guild_builder = rest.guild_builder("My Server!")

    category_id = guild_builder.add_category("My safe place")
    channel_id = guild_builder.add_text_channel("general", parent_id=category_id)

    await guild_builder.create()
    ```
    """

    # Required arguments.
    _entity_factory: entity_factory_.EntityFactory = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    _executor: typing.Optional[concurrent.futures.Executor] = attr.field(
        metadata={attr_extensions.SKIP_DEEP_COPY: True}
    )
    _name: str = attr.field()
    _request_call: typing.Callable[
        ..., typing.Coroutine[None, None, typing.Union[None, data_binding.JSONObject, data_binding.JSONArray]]
    ] = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})

    # Optional arguments.
    default_message_notifications: undefined.UndefinedOr[guilds.GuildMessageNotificationsLevel] = attr.field(
        default=undefined.UNDEFINED
    )
    explicit_content_filter_level: undefined.UndefinedOr[guilds.GuildExplicitContentFilterLevel] = attr.field(
        default=undefined.UNDEFINED
    )
    icon: undefined.UndefinedOr[files.Resourceish] = attr.field(default=undefined.UNDEFINED)
    verification_level: undefined.UndefinedOr[typing.Union[guilds.GuildVerificationLevel, int]] = attr.field(
        default=undefined.UNDEFINED
    )

    # Non-arguments
    _channels: typing.MutableSequence[data_binding.JSONObject] = attr.field(factory=list, init=False)
    _counter: int = attr.field(default=0, init=False)
    _roles: typing.MutableSequence[data_binding.JSONObject] = attr.field(factory=list, init=False)

    @property
    def name(self) -> str:
        return self._name

    async def create(self) -> guilds.RESTGuild:
        route = routes.POST_GUILDS.compile()
        payload = data_binding.JSONObjectBuilder()
        payload.put("name", self.name)
        payload.put_array("roles", self._roles if self._roles else undefined.UNDEFINED)
        payload.put_array("channels", self._channels if self._channels else undefined.UNDEFINED)
        payload.put("verification_level", self.verification_level)
        payload.put("default_message_notifications", self.default_message_notifications)
        payload.put("explicit_content_filter", self.explicit_content_filter_level)

        if self.icon is not undefined.UNDEFINED:
            icon = files.ensure_resource(self.icon)

            async with icon.stream(executor=self._executor) as stream:
                data_uri = await stream.data_uri()
                payload.put("icon", data_uri)

        response = await self._request_call(route, json=payload)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_rest_guild(response)

    def add_role(
        self,
        name: str,
        /,
        *,
        color: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
        colour: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
        hoist: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        mentionable: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        permissions: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    ) -> snowflakes.Snowflake:
        if not undefined.any_undefined(color, colour):
            raise TypeError("Cannot specify 'color' and 'colour' together.")

        if len(self._roles) == 0:
            if name != "@everyone":
                raise ValueError("First role must always be the '@everyone' role")
            if not undefined.all_undefined(color, colour, hoist, mentionable, position):
                raise ValueError(
                    "Cannot pass 'color', 'colour', 'hoist', 'mentionable' nor 'position' to the '@everyone' role."
                )

        snowflake_id = self._new_snowflake()
        payload = data_binding.JSONObjectBuilder()
        payload.put_snowflake("id", snowflake_id)
        payload.put("name", name)
        payload.put("color", color, conversion=colors.Color.of)
        payload.put("color", colour, conversion=colors.Color.of)
        payload.put("hoist", hoist)
        payload.put("mentionable", mentionable)
        payload.put("permissions", permissions)
        payload.put("position", position)
        self._roles.append(payload)
        return snowflake_id

    def add_category(
        self,
        name: str,
        /,
        *,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Collection[channels.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> snowflakes.Snowflake:
        snowflake_id = self._new_snowflake()
        payload = data_binding.JSONObjectBuilder()
        payload.put_snowflake("id", snowflake_id)
        payload.put("name", name)
        payload.put("type", channels.ChannelType.GUILD_CATEGORY)
        payload.put("position", position)
        payload.put("nsfw", nsfw)

        payload.put_array(
            "permission_overwrites",
            permission_overwrites,
            conversion=self._entity_factory.serialize_permission_overwrite,
        )

        self._channels.append(payload)
        return snowflake_id

    def add_text_channel(
        self,
        name: str,
        /,
        *,
        parent_id: undefined.UndefinedOr[snowflakes.Snowflake] = undefined.UNDEFINED,
        topic: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Collection[channels.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> snowflakes.Snowflake:
        snowflake_id = self._new_snowflake()
        payload = data_binding.JSONObjectBuilder()
        payload.put_snowflake("id", snowflake_id)
        payload.put("name", name)
        payload.put("type", channels.ChannelType.GUILD_TEXT)
        payload.put("topic", topic)
        payload.put("rate_limit_per_user", rate_limit_per_user, conversion=time.timespan_to_int)
        payload.put("position", position)
        payload.put("nsfw", nsfw)
        payload.put_snowflake("parent_id", parent_id)

        payload.put_array(
            "permission_overwrites",
            permission_overwrites,
            conversion=self._entity_factory.serialize_permission_overwrite,
        )

        self._channels.append(payload)
        return snowflake_id

    def add_voice_channel(
        self,
        name: str,
        /,
        *,
        parent_id: undefined.UndefinedOr[snowflakes.Snowflake] = undefined.UNDEFINED,
        bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        video_quality_mode: undefined.UndefinedOr[typing.Union[channels.VideoQualityMode, int]] = undefined.UNDEFINED,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Collection[channels.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        region: undefined.UndefinedNoneOr[typing.Union[voices.VoiceRegion, str]],
        user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    ) -> snowflakes.Snowflake:
        snowflake_id = self._new_snowflake()
        payload = data_binding.JSONObjectBuilder()
        payload.put_snowflake("id", snowflake_id)
        payload.put("name", name)
        payload.put("type", channels.ChannelType.GUILD_VOICE)
        payload.put("video_quality_mode", video_quality_mode)
        payload.put("bitrate", bitrate)
        payload.put("position", position)
        payload.put("user_limit", user_limit)
        payload.put_snowflake("parent_id", parent_id)
        payload.put("rtc_region", region, conversion=str)

        payload.put_array(
            "permission_overwrites",
            permission_overwrites,
            conversion=self._entity_factory.serialize_permission_overwrite,
        )

        self._channels.append(payload)
        return snowflake_id

    def add_stage_channel(
        self,
        name: str,
        /,
        *,
        parent_id: undefined.UndefinedOr[snowflakes.Snowflake] = undefined.UNDEFINED,
        bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Collection[channels.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        region: undefined.UndefinedNoneOr[typing.Union[voices.VoiceRegion, str]],
        user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    ) -> snowflakes.Snowflake:
        snowflake_id = self._new_snowflake()
        payload = data_binding.JSONObjectBuilder()
        payload.put_snowflake("id", snowflake_id)
        payload.put("name", name)
        payload.put("type", channels.ChannelType.GUILD_STAGE)
        payload.put("bitrate", bitrate)
        payload.put("position", position)
        payload.put("user_limit", user_limit)
        payload.put_snowflake("parent_id", parent_id)
        payload.put("rtc_region", region, conversion=str)

        payload.put_array(
            "permission_overwrites",
            permission_overwrites,
            conversion=self._entity_factory.serialize_permission_overwrite,
        )

        self._channels.append(payload)
        return snowflake_id

    def _new_snowflake(self) -> snowflakes.Snowflake:
        value = self._counter
        self._counter += 1
        return snowflakes.Snowflake.from_data(time.utc_datetime(), 0, 0, value)


# We use an explicit forward reference for this, since this breaks potential
# circular import issues (once the file has executed, using those resources is
# not an issue for us).
class MessageIterator(iterators.BufferedLazyIterator["messages.Message"]):
    """Implementation of an iterator for message history."""

    __slots__: typing.Sequence[str] = ("_entity_factory", "_request_call", "_direction", "_first_id", "_route")

    def __init__(
        self,
        entity_factory: entity_factory_.EntityFactory,
        request_call: typing.Callable[
            ..., typing.Coroutine[None, None, typing.Union[None, data_binding.JSONObject, data_binding.JSONArray]]
        ],
        channel: snowflakes.SnowflakeishOr[channels.TextableChannel],
        direction: str,
        first_id: undefined.UndefinedOr[str],
    ) -> None:
        super().__init__()
        self._entity_factory = entity_factory
        self._request_call = request_call
        self._direction = direction
        self._first_id = first_id
        self._route = routes.GET_CHANNEL_MESSAGES.compile(channel=channel)

    async def _next_chunk(self) -> typing.Optional[typing.Generator[messages.Message, typing.Any, None]]:
        query = data_binding.StringMapBuilder()
        query.put(self._direction, self._first_id)
        query.put("limit", 100)

        chunk = await self._request_call(compiled_route=self._route, query=query)
        assert isinstance(chunk, list)

        if not chunk:
            return None
        if self._direction == "after":
            chunk.reverse()

        self._first_id = chunk[-1]["id"]
        return (self._entity_factory.deserialize_message(m) for m in chunk)


# We use an explicit forward reference for this, since this breaks potential
# circular import issues (once the file has executed, using those resources is
# not an issue for us).
class ReactorIterator(iterators.BufferedLazyIterator["users.User"]):
    """Implementation of an iterator for message reactions."""

    __slots__: typing.Sequence[str] = ("_entity_factory", "_first_id", "_route", "_request_call")

    def __init__(
        self,
        entity_factory: entity_factory_.EntityFactory,
        request_call: typing.Callable[
            ..., typing.Coroutine[None, None, typing.Union[None, data_binding.JSONObject, data_binding.JSONArray]]
        ],
        channel: snowflakes.SnowflakeishOr[channels.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages.PartialMessage],
        emoji: str,
    ) -> None:
        super().__init__()
        self._entity_factory = entity_factory
        self._request_call = request_call
        self._first_id = undefined.UNDEFINED
        self._route = routes.GET_REACTIONS.compile(channel=channel, message=message, emoji=emoji)

    async def _next_chunk(self) -> typing.Optional[typing.Generator[users.User, typing.Any, None]]:
        query = data_binding.StringMapBuilder()
        query.put("after", self._first_id)
        query.put("limit", 100)

        chunk = await self._request_call(compiled_route=self._route, query=query)
        assert isinstance(chunk, list)

        if not chunk:
            return None

        self._first_id = chunk[-1]["id"]
        return (self._entity_factory.deserialize_user(u) for u in chunk)


# We use an explicit forward reference for this, since this breaks potential
# circular import issues (once the file has executed, using those resources is
# not an issue for us).
class OwnGuildIterator(iterators.BufferedLazyIterator["applications.OwnGuild"]):
    """Implementation of an iterator for retrieving guilds you are in."""

    __slots__: typing.Sequence[str] = ("_entity_factory", "_request_call", "_route", "_newest_first", "_first_id")

    def __init__(
        self,
        entity_factory: entity_factory_.EntityFactory,
        request_call: typing.Callable[
            ..., typing.Coroutine[None, None, typing.Union[None, data_binding.JSONObject, data_binding.JSONArray]]
        ],
        newest_first: bool,
        first_id: str,
    ) -> None:
        super().__init__()
        self._entity_factory = entity_factory
        self._newest_first = newest_first
        self._request_call = request_call
        self._first_id = first_id
        self._route = routes.GET_MY_GUILDS.compile()

    async def _next_chunk(self) -> typing.Optional[typing.Generator[applications.OwnGuild, typing.Any, None]]:
        query = data_binding.StringMapBuilder()
        query.put("before" if self._newest_first else "after", self._first_id)
        # We rely on Discord's default for the limit here since for this endpoint this has always scaled
        # along side the maximum page size limit to match the maximum amount of guilds a user can be in.

        chunk = await self._request_call(compiled_route=self._route, query=query)
        assert isinstance(chunk, list)

        if not chunk:
            return None

        if self._newest_first:
            chunk.reverse()

        self._first_id = chunk[-1]["id"]
        return (self._entity_factory.deserialize_own_guild(g) for g in chunk)


# We use an explicit forward reference for this, since this breaks potential
# circular import issues (once the file has executed, using those resources is
# not an issue for us).
class MemberIterator(iterators.BufferedLazyIterator["guilds.Member"]):
    """Implementation of an iterator for retrieving members in a guild."""

    __slots__: typing.Sequence[str] = ("_entity_factory", "_guild_id", "_request_call", "_route", "_first_id")

    def __init__(
        self,
        entity_factory: entity_factory_.EntityFactory,
        request_call: typing.Callable[
            ..., typing.Coroutine[None, None, typing.Union[None, data_binding.JSONObject, data_binding.JSONArray]]
        ],
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    ) -> None:
        super().__init__()
        self._guild_id = snowflakes.Snowflake(str(int(guild)))
        self._route = routes.GET_GUILD_MEMBERS.compile(guild=guild)
        self._request_call = request_call
        self._entity_factory = entity_factory
        # This starts at the default provided by Discord instead of the max snowflake
        # because that caused Discord to take about 2 seconds more to return the first response.
        self._first_id = undefined.UNDEFINED

    async def _next_chunk(self) -> typing.Optional[typing.Generator[guilds.Member, typing.Any, None]]:
        query = data_binding.StringMapBuilder()
        query.put("after", self._first_id)
        query.put("limit", 1000)

        chunk = await self._request_call(compiled_route=self._route, query=query)
        assert isinstance(chunk, list)

        if not chunk:
            return None

        self._first_id = chunk[-1]["user"]["id"]

        return (self._entity_factory.deserialize_member(m, guild_id=self._guild_id) for m in chunk)


# We use an explicit forward reference for this, since this breaks potential
# circular import issues (once the file has executed, using those resources is
# not an issue for us).
class ScheduledEventUserIterator(iterators.BufferedLazyIterator["scheduled_events.ScheduledEventUser"]):
    """Implementation of an iterator for retrieving the users subscribed to a scheduled event."""

    __slots__: typing.Sequence[str] = (
        "_entity_factory",
        "_first_id",
        "_guild_id",
        "_newest_first",
        "_request_call",
        "_route",
    )

    def __init__(
        self,
        entity_factory: entity_factory_.EntityFactory,
        request_call: typing.Callable[
            ..., typing.Coroutine[None, None, typing.Union[None, data_binding.JSONObject, data_binding.JSONArray]]
        ],
        newest_first: bool,
        first_id: str,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        event: snowflakes.SnowflakeishOr[scheduled_events.ScheduledEvent],
    ) -> None:
        super().__init__()
        self._entity_factory = entity_factory
        self._first_id = first_id
        self._guild_id = snowflakes.Snowflake(guild)
        self._newest_first = newest_first
        self._request_call = request_call
        self._route = routes.GET_GUILD_SCHEDULED_EVENT_USERS.compile(guild=guild, scheduled_event=event)

    async def _next_chunk(
        self,
    ) -> typing.Optional[typing.Generator[scheduled_events.ScheduledEventUser, typing.Any, None]]:
        query = data_binding.StringMapBuilder()
        query.put("before" if self._newest_first else "after", self._first_id)
        query.put("limit", 100)
        query.put("with_member", True)

        chunk = await self._request_call(compiled_route=self._route, query=query)
        assert isinstance(chunk, list)

        if not chunk:
            return None

        if self._newest_first:
            # These are always returned in ascending order by `.user.id`.
            chunk.reverse()

        self._first_id = chunk[-1]["user"]["id"]
        return (self._entity_factory.deserialize_scheduled_event_user(u, guild_id=self._guild_id) for u in chunk)


# We use an explicit forward reference for this, since this breaks potential
# circular import issues (once the file has executed, using those resources is
# not an issue for us).
class AuditLogIterator(iterators.LazyIterator["audit_logs.AuditLog"]):
    """Iterator implementation for an audit log."""

    __slots__: typing.Sequence[str] = (
        "_entity_factory",
        "_action_type",
        "_request_call",
        "_route",
        "_first_id",
        "_user",
    )

    def __init__(
        self,
        entity_factory: entity_factory_.EntityFactory,
        request_call: typing.Callable[
            ..., typing.Coroutine[None, None, typing.Union[None, data_binding.JSONObject, data_binding.JSONArray]]
        ],
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        before: undefined.UndefinedOr[str],
        user: undefined.UndefinedOr[snowflakes.SnowflakeishOr[users.PartialUser]],
        action_type: undefined.UndefinedOr[typing.Union["audit_logs.AuditLogEventType", int]],
    ) -> None:
        self._action_type = action_type
        self._entity_factory = entity_factory
        self._first_id = before
        self._request_call = request_call
        self._route = routes.GET_GUILD_AUDIT_LOGS.compile(guild=guild)
        self._user = user

    async def __anext__(self) -> audit_logs.AuditLog:
        query = data_binding.StringMapBuilder()
        query.put("limit", 100)
        query.put("user_id", self._user)
        query.put("action_type", self._action_type, conversion=int)
        query.put("before", self._first_id)

        response = await self._request_call(compiled_route=self._route, query=query)
        assert isinstance(response, dict)

        audit_log_entries = response["audit_log_entries"]
        if not audit_log_entries:
            raise StopAsyncIteration

        log = self._entity_factory.deserialize_audit_log(response)
        # Since deserialize_audit_log may skip entries it doesn't recognise,
        # first_id has to be calculated based on the raw payload as log.entries
        # may be missing entries.
        self._first_id = str(min(entry["id"] for entry in audit_log_entries))
        return log


@attr_extensions.with_copy
@attr.define(kw_only=False, weakref_slot=False)
class InteractionAutocompleteBuilder(special_endpoints.InteractionAutocompleteBuilder):
    """Standard implementation of `hikari.api.special_endpoints.InteractionAutocompleteBuilder`."""

    _choices: typing.Sequence[commands.CommandChoice] = attr.field(factory=list)

    @property
    def type(self) -> typing.Literal[base_interactions.ResponseType.AUTOCOMPLETE]:
        return base_interactions.ResponseType.AUTOCOMPLETE

    @property
    def choices(self) -> typing.Sequence[commands.CommandChoice]:
        return self._choices

    def set_choices(
        self: _InteractionAutocompleteBuilderT, choices: typing.Sequence[commands.CommandChoice], /
    ) -> _InteractionAutocompleteBuilderT:
        """Set autocomplete choices.

        Returns
        -------
        InteractionAutocompleteBuilder
            Object of this builder.
        """
        self._choices = choices
        return self

    def build(
        self, _: entity_factory_.EntityFactory, /
    ) -> typing.Tuple[data_binding.JSONObject, typing.Sequence[files.Resource[files.AsyncReader]]]:
        data = {"choices": [{"name": choice.name, "value": choice.value} for choice in self._choices]}
        return {"type": self.type, "data": data}, ()


@attr_extensions.with_copy
@attr.define(kw_only=False, weakref_slot=False)
class InteractionDeferredBuilder(special_endpoints.InteractionDeferredBuilder):
    """Standard implementation of `hikari.api.special_endpoints.InteractionDeferredBuilder`.

    Parameters
    ----------
    type : hikari.interactions.base_interactions.DeferredResponseTypesT
        The type of interaction response this is.
    """

    # Required arguments.
    _type: base_interactions.DeferredResponseTypesT = attr.field(
        converter=base_interactions.ResponseType,
        validator=attr.validators.in_(base_interactions.DEFERRED_RESPONSE_TYPES),
    )

    _flags: typing.Union[undefined.UndefinedType, int, messages.MessageFlag] = attr.field(
        default=undefined.UNDEFINED, kw_only=True
    )

    @property
    def type(self) -> base_interactions.DeferredResponseTypesT:
        return self._type

    @property
    def flags(self) -> typing.Union[undefined.UndefinedType, int, messages.MessageFlag]:
        return self._flags

    def set_flags(
        self: _InteractionDeferredBuilderT, flags: typing.Union[undefined.UndefinedType, int, messages.MessageFlag], /
    ) -> _InteractionDeferredBuilderT:
        self._flags = flags
        return self

    def build(
        self, _: entity_factory_.EntityFactory, /
    ) -> typing.Tuple[data_binding.JSONObject, typing.Sequence[files.Resource[files.AsyncReader]]]:
        if self._flags is not undefined.UNDEFINED:
            return {"type": self._type, "data": {"flags": self._flags}}, ()

        return {"type": self._type}, ()


@attr_extensions.with_copy
@attr.define(kw_only=False, weakref_slot=False)
class InteractionMessageBuilder(special_endpoints.InteractionMessageBuilder):
    """Standard implementation of `hikari.api.special_endpoints.InteractionMessageBuilder`.

    Parameters
    ----------
    type : hikari.interactions.base_interactions.MessageResponseTypesT
        The type of interaction response this is.

    Other Parameters
    ----------------
    content : hikari.undefined.UndefinedOr[str]
        The content of this response, if supplied. This follows the same rules
        as "content" on create message.
    """

    # Required arguments.
    _type: base_interactions.MessageResponseTypesT = attr.field(
        converter=base_interactions.ResponseType,
        validator=attr.validators.in_(base_interactions.MESSAGE_RESPONSE_TYPES),
    )

    # Not-required arguments.
    _content: undefined.UndefinedOr[str] = attr.field(default=undefined.UNDEFINED)

    # Key-word only not-required arguments.
    _flags: typing.Union[int, messages.MessageFlag, undefined.UndefinedType] = attr.field(
        default=undefined.UNDEFINED, kw_only=True
    )
    _is_tts: undefined.UndefinedOr[bool] = attr.field(default=undefined.UNDEFINED, kw_only=True)
    _mentions_everyone: undefined.UndefinedOr[bool] = attr.field(default=undefined.UNDEFINED, kw_only=True)
    _role_mentions: undefined.UndefinedOr[
        typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
    ] = attr.field(default=undefined.UNDEFINED, kw_only=True)
    _user_mentions: undefined.UndefinedOr[
        typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
    ] = attr.field(default=undefined.UNDEFINED, kw_only=True)
    _attachments: undefined.UndefinedOr[typing.List[files.Resourceish]] = attr.field(
        default=undefined.UNDEFINED, kw_only=True
    )
    _components: undefined.UndefinedOr[typing.List[special_endpoints.ComponentBuilder]] = attr.field(
        default=undefined.UNDEFINED, kw_only=True
    )
    _embeds: undefined.UndefinedOr[typing.List[embeds_.Embed]] = attr.field(default=undefined.UNDEFINED, kw_only=True)

    @property
    def attachments(self) -> undefined.UndefinedOr[typing.Sequence[files.Resourceish]]:
        return self._attachments.copy() if self._attachments is not undefined.UNDEFINED else undefined.UNDEFINED

    @property
    def content(self) -> undefined.UndefinedOr[str]:
        return self._content

    @property
    def components(self) -> undefined.UndefinedOr[typing.Sequence[special_endpoints.ComponentBuilder]]:
        return self._components.copy() if self._components is not undefined.UNDEFINED else undefined.UNDEFINED

    @property
    def embeds(self) -> undefined.UndefinedOr[typing.Sequence[embeds_.Embed]]:
        return self._embeds.copy() if self._embeds is not undefined.UNDEFINED else undefined.UNDEFINED

    @property
    def flags(self) -> typing.Union[undefined.UndefinedType, int, messages.MessageFlag]:
        return self._flags

    @property
    def is_tts(self) -> undefined.UndefinedOr[bool]:
        return self._is_tts

    @property
    def mentions_everyone(self) -> undefined.UndefinedOr[bool]:
        return self._mentions_everyone

    @property
    def role_mentions(
        self,
    ) -> undefined.UndefinedOr[typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]]:
        return self._role_mentions

    @property
    def type(self) -> base_interactions.MessageResponseTypesT:
        return self._type

    @property
    def user_mentions(
        self,
    ) -> undefined.UndefinedOr[typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]]:
        return self._user_mentions

    def add_attachment(
        self: _InteractionMessageBuilderT, attachment: files.Resourceish, /
    ) -> _InteractionMessageBuilderT:
        if self._attachments is undefined.UNDEFINED:
            self._attachments = []

        self._attachments.append(attachment)
        return self

    def add_component(
        self: _InteractionMessageBuilderT, component: special_endpoints.ComponentBuilder, /
    ) -> _InteractionMessageBuilderT:
        if self._components is undefined.UNDEFINED:
            self._components = []

        self._components.append(component)
        return self

    def add_embed(self: _InteractionMessageBuilderT, embed: embeds_.Embed, /) -> _InteractionMessageBuilderT:
        if self._embeds is undefined.UNDEFINED:
            self._embeds = []

        self._embeds.append(embed)
        return self

    def set_content(
        self: _InteractionMessageBuilderT, content: undefined.UndefinedOr[str], /
    ) -> _InteractionMessageBuilderT:
        self._content = str(content) if content is not undefined.UNDEFINED else undefined.UNDEFINED
        return self

    def set_flags(
        self: _InteractionMessageBuilderT, flags: typing.Union[undefined.UndefinedType, int, messages.MessageFlag], /
    ) -> _InteractionMessageBuilderT:
        self._flags = flags
        return self

    def set_tts(self: _InteractionMessageBuilderT, tts: undefined.UndefinedOr[bool], /) -> _InteractionMessageBuilderT:
        self._is_tts = tts
        return self

    def set_mentions_everyone(
        self: _InteractionMessageBuilderT, state: undefined.UndefinedOr[bool] = undefined.UNDEFINED, /
    ) -> _InteractionMessageBuilderT:
        self._mentions_everyone = state
        return self

    def set_role_mentions(
        self: _InteractionMessageBuilderT,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
        /,
    ) -> _InteractionMessageBuilderT:
        self._role_mentions = role_mentions
        return self

    def set_user_mentions(
        self: _InteractionMessageBuilderT,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        /,
    ) -> _InteractionMessageBuilderT:
        self._user_mentions = user_mentions
        return self

    def build(
        self, entity_factory: entity_factory_.EntityFactory, /
    ) -> typing.Tuple[data_binding.JSONObject, typing.Sequence[files.Resource[files.AsyncReader]]]:
        data = data_binding.JSONObjectBuilder()
        data.put("content", self.content)

        if self._attachments:
            final_attachments = [files.ensure_resource(attachment) for attachment in self._attachments]

        else:
            final_attachments = []

        if self._embeds is not undefined.UNDEFINED:
            embeds: typing.List[data_binding.JSONObject] = []
            for embed, attachments in map(entity_factory.serialize_embed, self._embeds):
                final_attachments.extend(attachments)
                embeds.append(embed)

            data["embeds"] = embeds

        data.put_array("components", self._components, conversion=lambda component: component.build())
        data.put("flags", self.flags)
        data.put("tts", self.is_tts)

        if (
            not undefined.all_undefined(self.mentions_everyone, self.user_mentions, self.role_mentions)
            or self.type is base_interactions.ResponseType.MESSAGE_CREATE
        ):
            data["allowed_mentions"] = mentions.generate_allowed_mentions(
                self.mentions_everyone, undefined.UNDEFINED, self.user_mentions, self.role_mentions
            )

        return {"type": self._type, "data": data}, final_attachments


@attr.define(kw_only=False, weakref_slot=False)
class CommandBuilder(special_endpoints.CommandBuilder):
    """Standard implementation of `hikari.api.special_endpoints.CommandBuilder`."""

    _name: str = attr.field()

    _id: undefined.UndefinedOr[snowflakes.Snowflake] = attr.field(default=undefined.UNDEFINED, kw_only=True)
    _default_permission: undefined.UndefinedOr[bool] = attr.field(default=undefined.UNDEFINED, kw_only=True)

    @property
    def id(self) -> undefined.UndefinedOr[snowflakes.Snowflake]:
        return self._id

    @property
    def default_permission(self) -> undefined.UndefinedOr[bool]:
        return self._default_permission

    @property
    def name(self) -> str:
        return self._name

    def set_id(self: _CommandBuilderT, id_: undefined.UndefinedOr[snowflakes.Snowflakeish], /) -> _CommandBuilderT:
        self._id = snowflakes.Snowflake(id_) if id_ is not undefined.UNDEFINED else undefined.UNDEFINED
        return self

    def set_default_permission(self: _CommandBuilderT, state: undefined.UndefinedOr[bool], /) -> _CommandBuilderT:
        self._default_permission = state
        return self

    def build(self, entity_factory: entity_factory_.EntityFactory, /) -> data_binding.JSONObjectBuilder:
        data = data_binding.JSONObjectBuilder()
        data["name"] = self._name
        data["type"] = self.type
        data.put_snowflake("id", self._id)
        data.put("default_permission", self._default_permission)
        return data


@attr_extensions.with_copy
@attr.define(kw_only=False, weakref_slot=False)
class SlashCommandBuilder(CommandBuilder, special_endpoints.SlashCommandBuilder):
    """Builder class for slash commands."""

    _description: str = attr.field()
    _options: typing.List[commands.CommandOption] = attr.field(factory=list, kw_only=True)

    @property
    def description(self) -> str:
        return self._description

    @property
    def type(self) -> commands.CommandType:
        return commands.CommandType.SLASH

    def add_option(self: _SlashCommandBuilderT, option: commands.CommandOption) -> _SlashCommandBuilderT:
        self._options.append(option)
        return self

    @property
    def options(self) -> typing.Sequence[commands.CommandOption]:
        return self._options.copy()

    def build(self, entity_factory: entity_factory_.EntityFactory, /) -> data_binding.JSONObjectBuilder:
        data = super().build(entity_factory)
        data.put("description", self._description)
        data.put_array("options", self._options, conversion=entity_factory.serialize_command_option)
        return data

    async def create(
        self,
        rest: rest_api.RESTClient,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        /,
        *,
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> commands.SlashCommand:
        return await rest.create_slash_command(
            application,
            self._name,
            self._description,
            guild=guild,
            default_permission=self._default_permission,
            options=self._options,
        )


@attr_extensions.with_copy
@attr.define(kw_only=False, weakref_slot=False)
class ContextMenuCommandBuilder(CommandBuilder, special_endpoints.ContextMenuCommandBuilder):
    """Builder class for context menu commands."""

    _type: commands.CommandType = attr.field()
    # name is re-declared here to ensure type is before it in the initializer's args.
    _name: str = attr.field()

    @property
    def type(self) -> commands.CommandType:
        return self._type

    async def create(
        self,
        rest: rest_api.RESTClient,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        /,
        *,
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> commands.ContextMenuCommand:
        return await rest.create_context_menu_command(
            application, self._type, self._name, guild=guild, default_permission=self._default_permission
        )


def _build_emoji(
    emoji: typing.Union[snowflakes.Snowflakeish, emojis.Emoji, str, undefined.UndefinedType] = undefined.UNDEFINED
) -> typing.Tuple[undefined.UndefinedOr[str], undefined.UndefinedOr[str]]:
    """Build an emoji into the format accepted in buttons.

    Parameters
    ----------
    emoji : typing.Union[hikari.snowflakes.Snowflakeish, hikari.emojis.Emoji, str, hikari.undefined.UndefinedType]
        The ID, object or raw string of an emoji to set on a component.

    Returns
    -------
    typing.Tuple[hikari.undefined.UndefinedOr[str], hikari.undefined.UndefinedOr[str]]
        A union of the custom emoji's id if defined (index 0) or the unicode
        emoji's string representation (index 1).
    """  # noqa E501 - Line too long
    # Since these builder classes may be re-used, this method should be called when the builder is being constructed.
    if emoji is not undefined.UNDEFINED:
        if isinstance(emoji, (int, emojis.CustomEmoji)):
            return str(int(emoji)), undefined.UNDEFINED

        return undefined.UNDEFINED, str(emoji)

    return undefined.UNDEFINED, undefined.UNDEFINED


@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
class _ButtonBuilder(special_endpoints.ButtonBuilder[_ContainerProtoT]):
    _container: _ContainerProtoT = attr.field()
    _style: typing.Union[int, messages.ButtonStyle] = attr.field()
    _custom_id: undefined.UndefinedOr[str] = attr.field(default=undefined.UNDEFINED)
    _url: undefined.UndefinedOr[str] = attr.field(default=undefined.UNDEFINED)
    _emoji: typing.Union[snowflakes.Snowflakeish, emojis.Emoji, str, undefined.UndefinedType] = attr.field(
        default=undefined.UNDEFINED
    )
    _emoji_id: undefined.UndefinedOr[str] = attr.field(default=undefined.UNDEFINED)
    _emoji_name: undefined.UndefinedOr[str] = attr.field(default=undefined.UNDEFINED)
    _label: undefined.UndefinedOr[str] = attr.field(default=undefined.UNDEFINED)
    _is_disabled: bool = attr.field(default=False)

    @property
    def style(self) -> typing.Union[int, messages.ButtonStyle]:
        return self._style

    @property
    def emoji(self) -> typing.Union[snowflakes.Snowflakeish, emojis.Emoji, str, undefined.UndefinedType]:
        return self._emoji

    @property
    def label(self) -> undefined.UndefinedOr[str]:
        return self._label

    @property
    def is_disabled(self) -> bool:
        return self._is_disabled

    def set_emoji(
        self: _ButtonBuilderT,
        emoji: typing.Union[snowflakes.Snowflakeish, emojis.Emoji, str, undefined.UndefinedType],
        /,
    ) -> _ButtonBuilderT:
        self._emoji_id, self._emoji_name = _build_emoji(emoji)
        self._emoji = emoji
        return self

    def set_label(self: _ButtonBuilderT, label: undefined.UndefinedOr[str], /) -> _ButtonBuilderT:
        self._label = label
        return self

    def set_is_disabled(self: _ButtonBuilderT, state: bool, /) -> _ButtonBuilderT:
        self._is_disabled = state
        return self

    def add_to_container(self) -> _ContainerProtoT:
        self._container.add_component(self)
        return self._container

    def build(self) -> data_binding.JSONObject:
        data = data_binding.JSONObjectBuilder()

        data["type"] = messages.ComponentType.BUTTON
        data["style"] = self._style
        data["disabled"] = self._is_disabled
        data.put("label", self._label)

        if self._emoji_id is not undefined.UNDEFINED:
            data["emoji"] = {"id": self._emoji_id}

        elif self._emoji_name is not undefined.UNDEFINED:
            data["emoji"] = {"name": self._emoji_name}

        data.put("custom_id", self._custom_id)
        data.put("url", self._url)

        return data


@attr.define(kw_only=True, weakref_slot=False)
class LinkButtonBuilder(_ButtonBuilder[_ContainerProtoT], special_endpoints.LinkButtonBuilder[_ContainerProtoT]):
    """Builder class for link buttons."""

    _url: str = attr.field()

    @property
    def url(self) -> str:
        return self._url


@attr.define(kw_only=True, weakref_slot=False)
class InteractiveButtonBuilder(
    _ButtonBuilder[_ContainerProtoT], special_endpoints.InteractiveButtonBuilder[_ContainerProtoT]
):
    """Builder class for interactive buttons."""

    _custom_id: str = attr.field()

    @property
    def custom_id(self) -> str:
        return self._custom_id


@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
class _SelectOptionBuilder(special_endpoints.SelectOptionBuilder["_SelectMenuBuilderT"]):
    """Builder class for select menu options."""

    _menu: _SelectMenuBuilderT = attr.field()
    _label: str = attr.field()
    _value: str = attr.field()
    _description: undefined.UndefinedOr[str] = attr.field(default=undefined.UNDEFINED)
    _emoji: typing.Union[snowflakes.Snowflakeish, emojis.Emoji, str, undefined.UndefinedType] = attr.field(
        default=undefined.UNDEFINED
    )
    _emoji_id: undefined.UndefinedOr[str] = attr.field(default=undefined.UNDEFINED)
    _emoji_name: undefined.UndefinedOr[str] = attr.field(default=undefined.UNDEFINED)
    _is_default: bool = attr.field(default=False)

    @property
    def label(self) -> str:
        return self._label

    @property
    def value(self) -> str:
        return self._value

    @property
    def description(self) -> undefined.UndefinedOr[str]:
        return self._description

    @property
    def emoji(self) -> typing.Union[snowflakes.Snowflakeish, emojis.Emoji, str, undefined.UndefinedType]:
        return self._emoji

    @property
    def is_default(self) -> bool:
        return self._is_default

    def set_description(self: _SelectOptionBuilderT, value: undefined.UndefinedOr[str], /) -> _SelectOptionBuilderT:
        self._description = value
        return self

    def set_emoji(
        self: _SelectOptionBuilderT,
        emoji: typing.Union[snowflakes.Snowflakeish, emojis.Emoji, str, undefined.UndefinedType],
        /,
    ) -> _SelectOptionBuilderT:
        self._emoji_id, self._emoji_name = _build_emoji(emoji)
        self._emoji = emoji
        return self

    def set_is_default(self: _SelectOptionBuilderT, state: bool, /) -> _SelectOptionBuilderT:
        self._is_default = state
        return self

    def add_to_menu(self) -> _SelectMenuBuilderT:
        self._menu.add_raw_option(self)
        return self._menu

    def build(self) -> data_binding.JSONObject:
        data = data_binding.JSONObjectBuilder()

        data["label"] = self._label
        data["value"] = self._value
        data["default"] = self._is_default
        data.put("description", self._description)

        if self._emoji_id is not undefined.UNDEFINED:
            data["emoji"] = {"id": self._emoji_id}

        elif self._emoji_name is not undefined.UNDEFINED:
            data["emoji"] = {"name": self._emoji_name}

        return data


@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
class SelectMenuBuilder(special_endpoints.SelectMenuBuilder[_ContainerProtoT]):
    """Builder class for select menus."""

    _container: _ContainerProtoT = attr.field()
    _custom_id: str = attr.field()
    # Any has to be used here as we can't access Self type in this context
    _options: typing.List[special_endpoints.SelectOptionBuilder[typing.Any]] = attr.field(factory=list)
    _placeholder: undefined.UndefinedOr[str] = attr.field(default=undefined.UNDEFINED)
    _min_values: int = attr.field(default=0)
    _max_values: int = attr.field(default=1)
    _is_disabled: bool = attr.field(default=False)

    @property
    def custom_id(self) -> str:
        return self._custom_id

    @property
    def is_disabled(self) -> bool:
        return self._is_disabled

    @property
    def options(
        self: _SelectMenuBuilderT,
    ) -> typing.Sequence[special_endpoints.SelectOptionBuilder[_SelectMenuBuilderT]]:
        return self._options.copy()

    @property
    def placeholder(self) -> undefined.UndefinedOr[str]:
        return self._placeholder

    @property
    def min_values(self) -> int:
        return self._min_values

    @property
    def max_values(self) -> int:
        return self._max_values

    def add_option(
        self: _SelectMenuBuilderT, label: str, value: str, /
    ) -> special_endpoints.SelectOptionBuilder[_SelectMenuBuilderT]:
        return _SelectOptionBuilder(menu=self, label=label, value=value)

    def add_raw_option(
        self: _SelectMenuBuilderT, option: special_endpoints.SelectOptionBuilder[_SelectMenuBuilderT], /
    ) -> _SelectMenuBuilderT:
        self._options.append(option)
        return self

    def set_is_disabled(self: _SelectMenuBuilderT, state: bool, /) -> _SelectMenuBuilderT:
        self._is_disabled = state
        return self

    def set_placeholder(self: _SelectMenuBuilderT, value: undefined.UndefinedOr[str], /) -> _SelectMenuBuilderT:
        self._placeholder = value
        return self

    def set_min_values(self: _SelectMenuBuilderT, value: int, /) -> _SelectMenuBuilderT:
        self._min_values = value
        return self

    def set_max_values(self: _SelectMenuBuilderT, value: int, /) -> _SelectMenuBuilderT:
        self._max_values = value
        return self

    def add_to_container(self) -> _ContainerProtoT:
        self._container.add_component(self)
        return self._container

    def build(self) -> data_binding.JSONObject:
        data = data_binding.JSONObjectBuilder()

        data["type"] = messages.ComponentType.SELECT_MENU
        data["custom_id"] = self._custom_id
        data["options"] = [option.build() for option in self._options]
        data.put("placeholder", self._placeholder)
        data.put("min_values", self._min_values)
        data.put("max_values", self._max_values)
        data.put("disabled", self._is_disabled)
        return data


@attr.define(kw_only=True, weakref_slot=False)
class ActionRowBuilder(special_endpoints.ActionRowBuilder):
    """Standard implementation of `hikari.api.special_endpoints.ActionRowBuilder`."""

    _components: typing.List[special_endpoints.ComponentBuilder] = attr.field(factory=list)
    _stored_type: typing.Optional[messages.ComponentType] = attr.field(default=None)

    @property
    def components(self) -> typing.Sequence[special_endpoints.ComponentBuilder]:
        return self._components.copy()

    def _assert_can_add_type(self, type_: messages.ComponentType, /) -> None:
        if self._stored_type is not None and self._stored_type != type_:
            raise ValueError(
                f"{type_} component type cannot be added to a container which already holds {self._stored_type}"
            )

        self._stored_type = type_

    def add_component(self: _ActionRowBuilderT, component: special_endpoints.ComponentBuilder, /) -> _ActionRowBuilderT:
        self._components.append(component)
        return self

    @typing.overload
    def add_button(
        self: _ActionRowBuilderT, style: messages.InteractiveButtonTypesT, custom_id: str, /
    ) -> special_endpoints.InteractiveButtonBuilder[_ActionRowBuilderT]:
        ...

    @typing.overload
    def add_button(
        self: _ActionRowBuilderT,
        style: typing.Literal[messages.ButtonStyle.LINK, 5],
        url: str,
        /,
    ) -> special_endpoints.LinkButtonBuilder[_ActionRowBuilderT]:
        ...

    @typing.overload
    def add_button(
        self: _ActionRowBuilderT, style: typing.Union[int, messages.ButtonStyle], url_or_custom_id: str, /
    ) -> typing.Union[
        special_endpoints.LinkButtonBuilder[_ActionRowBuilderT],
        special_endpoints.InteractiveButtonBuilder[_ActionRowBuilderT],
    ]:
        ...

    def add_button(
        self: _ActionRowBuilderT, style: typing.Union[int, messages.ButtonStyle], url_or_custom_id: str, /
    ) -> typing.Union[
        special_endpoints.LinkButtonBuilder[_ActionRowBuilderT],
        special_endpoints.InteractiveButtonBuilder[_ActionRowBuilderT],
    ]:
        self._assert_can_add_type(messages.ComponentType.BUTTON)
        if style in messages.InteractiveButtonTypes:
            return InteractiveButtonBuilder(container=self, style=style, custom_id=url_or_custom_id)

        return LinkButtonBuilder(container=self, style=style, url=url_or_custom_id)

    def add_select_menu(
        self: _ActionRowBuilderT, custom_id: str, /
    ) -> special_endpoints.SelectMenuBuilder[_ActionRowBuilderT]:
        self._assert_can_add_type(messages.ComponentType.SELECT_MENU)
        return SelectMenuBuilder(container=self, custom_id=custom_id)

    def build(self) -> data_binding.JSONObject:
        return {
            "type": messages.ComponentType.ACTION_ROW,
            "components": [component.build() for component in self._components],
        }
#  
@attr.define(kw_only=True, weakref_slot=False)
class ActionRowBuilder(hikari.api.special_endpoints.ActionRowBuilder):
View Source
@attr.define(kw_only=True, weakref_slot=False)
class ActionRowBuilder(special_endpoints.ActionRowBuilder):
    """Standard implementation of `hikari.api.special_endpoints.ActionRowBuilder`."""

    _components: typing.List[special_endpoints.ComponentBuilder] = attr.field(factory=list)
    _stored_type: typing.Optional[messages.ComponentType] = attr.field(default=None)

    @property
    def components(self) -> typing.Sequence[special_endpoints.ComponentBuilder]:
        return self._components.copy()

    def _assert_can_add_type(self, type_: messages.ComponentType, /) -> None:
        if self._stored_type is not None and self._stored_type != type_:
            raise ValueError(
                f"{type_} component type cannot be added to a container which already holds {self._stored_type}"
            )

        self._stored_type = type_

    def add_component(self: _ActionRowBuilderT, component: special_endpoints.ComponentBuilder, /) -> _ActionRowBuilderT:
        self._components.append(component)
        return self

    @typing.overload
    def add_button(
        self: _ActionRowBuilderT, style: messages.InteractiveButtonTypesT, custom_id: str, /
    ) -> special_endpoints.InteractiveButtonBuilder[_ActionRowBuilderT]:
        ...

    @typing.overload
    def add_button(
        self: _ActionRowBuilderT,
        style: typing.Literal[messages.ButtonStyle.LINK, 5],
        url: str,
        /,
    ) -> special_endpoints.LinkButtonBuilder[_ActionRowBuilderT]:
        ...

    @typing.overload
    def add_button(
        self: _ActionRowBuilderT, style: typing.Union[int, messages.ButtonStyle], url_or_custom_id: str, /
    ) -> typing.Union[
        special_endpoints.LinkButtonBuilder[_ActionRowBuilderT],
        special_endpoints.InteractiveButtonBuilder[_ActionRowBuilderT],
    ]:
        ...

    def add_button(
        self: _ActionRowBuilderT, style: typing.Union[int, messages.ButtonStyle], url_or_custom_id: str, /
    ) -> typing.Union[
        special_endpoints.LinkButtonBuilder[_ActionRowBuilderT],
        special_endpoints.InteractiveButtonBuilder[_ActionRowBuilderT],
    ]:
        self._assert_can_add_type(messages.ComponentType.BUTTON)
        if style in messages.InteractiveButtonTypes:
            return InteractiveButtonBuilder(container=self, style=style, custom_id=url_or_custom_id)

        return LinkButtonBuilder(container=self, style=style, url=url_or_custom_id)

    def add_select_menu(
        self: _ActionRowBuilderT, custom_id: str, /
    ) -> special_endpoints.SelectMenuBuilder[_ActionRowBuilderT]:
        self._assert_can_add_type(messages.ComponentType.SELECT_MENU)
        return SelectMenuBuilder(container=self, custom_id=custom_id)

    def build(self) -> data_binding.JSONObject:
        return {
            "type": messages.ComponentType.ACTION_ROW,
            "components": [component.build() for component in self._components],
        }
Variables and properties

Sequence of the component builders registered within this action row.

Methods
#  def __init__(
   self,
   *,
   components: List[hikari.api.special_endpoints.ComponentBuilder] = NOTHING,
   stored_type: Optional[hikari.messages.ComponentType] = None
):
View Source
def __init__(self, *, components=NOTHING, stored_type=attr_dict['_stored_type'].default):
    if components is not NOTHING:
        self._components = components
    else:
        self._components = __attr_factory__components()
    self._stored_type = stored_type

Method generated by attrs for class ActionRowBuilder.

#  def add_button(
   self: ~_ActionRowBuilderT,
   style: Union[int, hikari.messages.ButtonStyle],
   url_or_custom_id: str,
   /
) -> Union[hikari.api.special_endpoints.LinkButtonBuilder[~_ActionRowBuilderT], hikari.api.special_endpoints.InteractiveButtonBuilder[~_ActionRowBuilderT]]:
View Source
    def add_button(
        self: _ActionRowBuilderT, style: typing.Union[int, messages.ButtonStyle], url_or_custom_id: str, /
    ) -> typing.Union[
        special_endpoints.LinkButtonBuilder[_ActionRowBuilderT],
        special_endpoints.InteractiveButtonBuilder[_ActionRowBuilderT],
    ]:
        self._assert_can_add_type(messages.ComponentType.BUTTON)
        if style in messages.InteractiveButtonTypes:
            return InteractiveButtonBuilder(container=self, style=style, custom_id=url_or_custom_id)

        return LinkButtonBuilder(container=self, style=style, url=url_or_custom_id)

Add a button component to this action row builder.

Parameters
  • style (typing.Union[int, hikari.messages.ButtonStyle]): The button's style.
  • url_or_custom_id (str): For interactive button styles this is a developer-defined custom identifier used to identify which button triggered component interactions.

    For Link button styles this is the URL the link button should redirect to.

Returns
  • typing.Union[LinkButtonBuilder[Self], InteractiveButtonBuilder[Self]]: Button builder object. ButtonBuilder.add_to_container should be called to finalise the button.
#  def add_component(
   self: ~_ActionRowBuilderT,
   component: hikari.api.special_endpoints.ComponentBuilder,
   /
) -> ~_ActionRowBuilderT:
View Source
    def add_component(self: _ActionRowBuilderT, component: special_endpoints.ComponentBuilder, /) -> _ActionRowBuilderT:
        self._components.append(component)
        return self

Add a component to this action row builder.

Warning: It is generally better to use ActionRowBuilder.add_button and ActionRowBuilder.add_select_menu to add your component to the builder. Those methods utilize this one.

Parameters
  • component (ComponentBuilder): The component builder to add to the action row.
Returns
  • ActionRowBuilder: The builder object to enable chained calls.
#  def add_select_menu(
   self: ~_ActionRowBuilderT,
   custom_id: str,
   /
) -> hikari.api.special_endpoints.SelectMenuBuilder[~_ActionRowBuilderT]:
View Source
    def add_select_menu(
        self: _ActionRowBuilderT, custom_id: str, /
    ) -> special_endpoints.SelectMenuBuilder[_ActionRowBuilderT]:
        self._assert_can_add_type(messages.ComponentType.SELECT_MENU)
        return SelectMenuBuilder(container=self, custom_id=custom_id)

Add a select menu component to this action row builder.

Parameters
  • custom_id (str): A developer-defined custom identifier used to identify which menu triggered component interactions.
Returns
#  def build(self) -> Dict[str, Any]:
View Source
    def build(self) -> data_binding.JSONObject:
        return {
            "type": messages.ComponentType.ACTION_ROW,
            "components": [component.build() for component in self._components],
        }

Build a JSON object from this builder.

Returns
#  
@attr.define(kw_only=False, weakref_slot=False)
class CommandBuilder(hikari.api.special_endpoints.CommandBuilder):
View Source
@attr.define(kw_only=False, weakref_slot=False)
class CommandBuilder(special_endpoints.CommandBuilder):
    """Standard implementation of `hikari.api.special_endpoints.CommandBuilder`."""

    _name: str = attr.field()

    _id: undefined.UndefinedOr[snowflakes.Snowflake] = attr.field(default=undefined.UNDEFINED, kw_only=True)
    _default_permission: undefined.UndefinedOr[bool] = attr.field(default=undefined.UNDEFINED, kw_only=True)

    @property
    def id(self) -> undefined.UndefinedOr[snowflakes.Snowflake]:
        return self._id

    @property
    def default_permission(self) -> undefined.UndefinedOr[bool]:
        return self._default_permission

    @property
    def name(self) -> str:
        return self._name

    def set_id(self: _CommandBuilderT, id_: undefined.UndefinedOr[snowflakes.Snowflakeish], /) -> _CommandBuilderT:
        self._id = snowflakes.Snowflake(id_) if id_ is not undefined.UNDEFINED else undefined.UNDEFINED
        return self

    def set_default_permission(self: _CommandBuilderT, state: undefined.UndefinedOr[bool], /) -> _CommandBuilderT:
        self._default_permission = state
        return self

    def build(self, entity_factory: entity_factory_.EntityFactory, /) -> data_binding.JSONObjectBuilder:
        data = data_binding.JSONObjectBuilder()
        data["name"] = self._name
        data["type"] = self.type
        data.put_snowflake("id", self._id)
        data.put("default_permission", self._default_permission)
        return data
Variables and properties
#  default_permission: Union[bool, hikari.undefined.UndefinedType]

Whether the command should be enabled by default (without any permissions).

#  name: str

Name to set for this command.

Warning: This should match the regex ^[\w-]{1,32}$ in Unicode mode and must be lowercase.

Return the type of this command.

Returns
Methods
#  def __init__(
   self,
   name: str,
   *,
   id: Union[hikari.snowflakes.Snowflake, hikari.undefined.UndefinedType] = UNDEFINED,
   default_permission: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED
):
View Source
def __init__(self, name, *, id=attr_dict['_id'].default, default_permission=attr_dict['_default_permission'].default):
    self._name = name
    self._id = id
    self._default_permission = default_permission

Method generated by attrs for class CommandBuilder.

View Source
    def build(self, entity_factory: entity_factory_.EntityFactory, /) -> data_binding.JSONObjectBuilder:
        data = data_binding.JSONObjectBuilder()
        data["name"] = self._name
        data["type"] = self.type
        data.put_snowflake("id", self._id)
        data.put("default_permission", self._default_permission)
        return data

Build a JSON object from this builder.

Parameters
Returns
#  
@abc.abstractmethod
async def create(
   self,
   rest: hikari.api.rest.RESTClient,
   application: Union[hikari.guilds.PartialApplication, hikari.snowflakes.Snowflake, int],
   /,
   *,
   guild: Union[hikari.guilds.PartialGuild, hikari.snowflakes.Snowflake, int, hikari.undefined.UndefinedType] = UNDEFINED
) -> hikari.commands.PartialCommand:
View Source
    @abc.abstractmethod
    async def create(
        self,
        rest: rest_api.RESTClient,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        /,
        *,
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> commands.PartialCommand:
        """Create this command through a REST call.

        Parameters
        ----------
        rest : hikari.api.rest.RESTClient
            The REST client to use to make this request.
        application : hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialApplication]
            The application to create this command for.

        Other Parameters
        ----------------
        guild : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]]
            The guild to create this command for.

            If left undefined then this command will be declared globally.

        Returns
        -------
        hikari.commands.PartialCommand
            The created command.
        """

Create this command through a REST call.

Parameters
Other Parameters
Returns
#  def set_default_permission(
   self: ~_CommandBuilderT,
   state: Union[bool, hikari.undefined.UndefinedType],
   /
) -> ~_CommandBuilderT:
View Source
    def set_default_permission(self: _CommandBuilderT, state: undefined.UndefinedOr[bool], /) -> _CommandBuilderT:
        self._default_permission = state
        return self

Whether this command should be enabled by default (without any permissions).

Parameters
Returns
  • CommandBuilder: Object of this command builder to allow for chained calls.
#  def set_id(
   self: ~_CommandBuilderT,
   id_: Union[hikari.snowflakes.Snowflake, int, hikari.undefined.UndefinedType],
   /
) -> ~_CommandBuilderT:
View Source
    def set_id(self: _CommandBuilderT, id_: undefined.UndefinedOr[snowflakes.Snowflakeish], /) -> _CommandBuilderT:
        self._id = snowflakes.Snowflake(id_) if id_ is not undefined.UNDEFINED else undefined.UNDEFINED
        return self

Set the ID of this command.

Parameters
Returns
  • CommandBuilder: Object of this command builder to allow for chained calls.
#  
@attr_extensions.with_copy
@attr.define(kw_only=False, weakref_slot=False)
class ContextMenuCommandBuilder(CommandBuilder, hikari.api.special_endpoints.ContextMenuCommandBuilder):
View Source
@attr_extensions.with_copy
@attr.define(kw_only=False, weakref_slot=False)
class ContextMenuCommandBuilder(CommandBuilder, special_endpoints.ContextMenuCommandBuilder):
    """Builder class for context menu commands."""

    _type: commands.CommandType = attr.field()
    # name is re-declared here to ensure type is before it in the initializer's args.
    _name: str = attr.field()

    @property
    def type(self) -> commands.CommandType:
        return self._type

    async def create(
        self,
        rest: rest_api.RESTClient,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        /,
        *,
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> commands.ContextMenuCommand:
        return await rest.create_context_menu_command(
            application, self._type, self._name, guild=guild, default_permission=self._default_permission
        )

Builder class for context menu commands.

Variables and properties
#  default_permission: Union[bool, hikari.undefined.UndefinedType]

Whether the command should be enabled by default (without any permissions).

#  name: str

Name to set for this command.

Warning: This should match the regex ^[\w-]{1,32}$ in Unicode mode and must be lowercase.

Return the type of this command.

Returns
Methods
#  def __init__(
   self,
   type: hikari.commands.CommandType,
   name: str,
   *,
   id: Union[hikari.snowflakes.Snowflake, hikari.undefined.UndefinedType] = UNDEFINED,
   default_permission: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED
):
View Source
def __init__(self, type, name, *, id=attr_dict['_id'].default, default_permission=attr_dict['_default_permission'].default):
    self._id = id
    self._default_permission = default_permission
    self._type = type
    self._name = name

Method generated by attrs for class ContextMenuCommandBuilder.

View Source
    def build(self, entity_factory: entity_factory_.EntityFactory, /) -> data_binding.JSONObjectBuilder:
        data = data_binding.JSONObjectBuilder()
        data["name"] = self._name
        data["type"] = self.type
        data.put_snowflake("id", self._id)
        data.put("default_permission", self._default_permission)
        return data

Build a JSON object from this builder.

Parameters
Returns
View Source
    async def create(
        self,
        rest: rest_api.RESTClient,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        /,
        *,
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> commands.ContextMenuCommand:
        return await rest.create_context_menu_command(
            application, self._type, self._name, guild=guild, default_permission=self._default_permission
        )

Create this command through a REST call.

Parameters
Other Parameters
Returns
#  def set_default_permission(
   self: ~_CommandBuilderT,
   state: Union[bool, hikari.undefined.UndefinedType],
   /
) -> ~_CommandBuilderT:
View Source
    def set_default_permission(self: _CommandBuilderT, state: undefined.UndefinedOr[bool], /) -> _CommandBuilderT:
        self._default_permission = state
        return self

Whether this command should be enabled by default (without any permissions).

Parameters
Returns
  • CommandBuilder: Object of this command builder to allow for chained calls.
#  def set_id(
   self: ~_CommandBuilderT,
   id_: Union[hikari.snowflakes.Snowflake, int, hikari.undefined.UndefinedType],
   /
) -> ~_CommandBuilderT:
View Source
    def set_id(self: _CommandBuilderT, id_: undefined.UndefinedOr[snowflakes.Snowflakeish], /) -> _CommandBuilderT:
        self._id = snowflakes.Snowflake(id_) if id_ is not undefined.UNDEFINED else undefined.UNDEFINED
        return self

Set the ID of this command.

Parameters
Returns
  • CommandBuilder: Object of this command builder to allow for chained calls.
#  
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
class GuildBuilder(hikari.api.special_endpoints.GuildBuilder):
View Source
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
class GuildBuilder(special_endpoints.GuildBuilder):
    """Result type of `hikari.api.rest.RESTClient.guild_builder`.

    This is used to create a guild in a tidy way using the HTTP API, since
    the logic behind creating a guild on an API level is somewhat confusing
    and detailed.

    .. note::
        This is a helper class that is used by `hikari.api.rest.RESTClient`.
        You should only ever need to use instances of this class that are
        produced by that API, thus, any details about the constructor are
        omitted from the following examples for brevity.

    Examples
    --------
    Creating an empty guild.

    ```py
    guild = await rest.guild_builder("My Server!").create()
    ```

    Creating a guild with an icon

    ```py
    from hikari.files import WebResourceStream

    guild_builder = rest.guild_builder("My Server!")
    guild_builder.icon = WebResourceStream("cat.png", "http://...")
    guild = await guild_builder.create()
    ```

    Adding roles to your guild.

    ```py
    from hikari.permissions import Permissions

    guild_builder = rest.guild_builder("My Server!")

    everyone_role_id = guild_builder.add_role("@everyone")
    admin_role_id = guild_builder.add_role("Admins", permissions=Permissions.ADMINISTRATOR)

    await guild_builder.create()
    ```

    .. warning::
        The first role must always be the `@everyone` role.

    .. note::
        If you call `add_role`, the default roles provided by Discord will
        be created. This also applies to the `add_` functions for
        text channels/voice channels/categories.

    .. note::
        Functions that return a `hikari.snowflakes.Snowflake` do
        **not** provide the final ID that the object will have once the
        API call is made. The returned IDs are only able to be used to
        re-reference particular objects while building the guild format.

        This is provided to allow creation of channels within categories,
        and to provide permission overwrites.

    Adding a text channel to your guild.

    ```py
    guild_builder = rest.guild_builder("My Server!")

    category_id = guild_builder.add_category("My safe place")
    channel_id = guild_builder.add_text_channel("general", parent_id=category_id)

    await guild_builder.create()
    ```
    """

    # Required arguments.
    _entity_factory: entity_factory_.EntityFactory = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
    _executor: typing.Optional[concurrent.futures.Executor] = attr.field(
        metadata={attr_extensions.SKIP_DEEP_COPY: True}
    )
    _name: str = attr.field()
    _request_call: typing.Callable[
        ..., typing.Coroutine[None, None, typing.Union[None, data_binding.JSONObject, data_binding.JSONArray]]
    ] = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})

    # Optional arguments.
    default_message_notifications: undefined.UndefinedOr[guilds.GuildMessageNotificationsLevel] = attr.field(
        default=undefined.UNDEFINED
    )
    explicit_content_filter_level: undefined.UndefinedOr[guilds.GuildExplicitContentFilterLevel] = attr.field(
        default=undefined.UNDEFINED
    )
    icon: undefined.UndefinedOr[files.Resourceish] = attr.field(default=undefined.UNDEFINED)
    verification_level: undefined.UndefinedOr[typing.Union[guilds.GuildVerificationLevel, int]] = attr.field(
        default=undefined.UNDEFINED
    )

    # Non-arguments
    _channels: typing.MutableSequence[data_binding.JSONObject] = attr.field(factory=list, init=False)
    _counter: int = attr.field(default=0, init=False)
    _roles: typing.MutableSequence[data_binding.JSONObject] = attr.field(factory=list, init=False)

    @property
    def name(self) -> str:
        return self._name

    async def create(self) -> guilds.RESTGuild:
        route = routes.POST_GUILDS.compile()
        payload = data_binding.JSONObjectBuilder()
        payload.put("name", self.name)
        payload.put_array("roles", self._roles if self._roles else undefined.UNDEFINED)
        payload.put_array("channels", self._channels if self._channels else undefined.UNDEFINED)
        payload.put("verification_level", self.verification_level)
        payload.put("default_message_notifications", self.default_message_notifications)
        payload.put("explicit_content_filter", self.explicit_content_filter_level)

        if self.icon is not undefined.UNDEFINED:
            icon = files.ensure_resource(self.icon)

            async with icon.stream(executor=self._executor) as stream:
                data_uri = await stream.data_uri()
                payload.put("icon", data_uri)

        response = await self._request_call(route, json=payload)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_rest_guild(response)

    def add_role(
        self,
        name: str,
        /,
        *,
        color: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
        colour: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
        hoist: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        mentionable: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        permissions: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    ) -> snowflakes.Snowflake:
        if not undefined.any_undefined(color, colour):
            raise TypeError("Cannot specify 'color' and 'colour' together.")

        if len(self._roles) == 0:
            if name != "@everyone":
                raise ValueError("First role must always be the '@everyone' role")
            if not undefined.all_undefined(color, colour, hoist, mentionable, position):
                raise ValueError(
                    "Cannot pass 'color', 'colour', 'hoist', 'mentionable' nor 'position' to the '@everyone' role."
                )

        snowflake_id = self._new_snowflake()
        payload = data_binding.JSONObjectBuilder()
        payload.put_snowflake("id", snowflake_id)
        payload.put("name", name)
        payload.put("color", color, conversion=colors.Color.of)
        payload.put("color", colour, conversion=colors.Color.of)
        payload.put("hoist", hoist)
        payload.put("mentionable", mentionable)
        payload.put("permissions", permissions)
        payload.put("position", position)
        self._roles.append(payload)
        return snowflake_id

    def add_category(
        self,
        name: str,
        /,
        *,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Collection[channels.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> snowflakes.Snowflake:
        snowflake_id = self._new_snowflake()
        payload = data_binding.JSONObjectBuilder()
        payload.put_snowflake("id", snowflake_id)
        payload.put("name", name)
        payload.put("type", channels.ChannelType.GUILD_CATEGORY)
        payload.put("position", position)
        payload.put("nsfw", nsfw)

        payload.put_array(
            "permission_overwrites",
            permission_overwrites,
            conversion=self._entity_factory.serialize_permission_overwrite,
        )

        self._channels.append(payload)
        return snowflake_id

    def add_text_channel(
        self,
        name: str,
        /,
        *,
        parent_id: undefined.UndefinedOr[snowflakes.Snowflake] = undefined.UNDEFINED,
        topic: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Collection[channels.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> snowflakes.Snowflake:
        snowflake_id = self._new_snowflake()
        payload = data_binding.JSONObjectBuilder()
        payload.put_snowflake("id", snowflake_id)
        payload.put("name", name)
        payload.put("type", channels.ChannelType.GUILD_TEXT)
        payload.put("topic", topic)
        payload.put("rate_limit_per_user", rate_limit_per_user, conversion=time.timespan_to_int)
        payload.put("position", position)
        payload.put("nsfw", nsfw)
        payload.put_snowflake("parent_id", parent_id)

        payload.put_array(
            "permission_overwrites",
            permission_overwrites,
            conversion=self._entity_factory.serialize_permission_overwrite,
        )

        self._channels.append(payload)
        return snowflake_id

    def add_voice_channel(
        self,
        name: str,
        /,
        *,
        parent_id: undefined.UndefinedOr[snowflakes.Snowflake] = undefined.UNDEFINED,
        bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        video_quality_mode: undefined.UndefinedOr[typing.Union[channels.VideoQualityMode, int]] = undefined.UNDEFINED,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Collection[channels.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        region: undefined.UndefinedNoneOr[typing.Union[voices.VoiceRegion, str]],
        user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    ) -> snowflakes.Snowflake:
        snowflake_id = self._new_snowflake()
        payload = data_binding.JSONObjectBuilder()
        payload.put_snowflake("id", snowflake_id)
        payload.put("name", name)
        payload.put("type", channels.ChannelType.GUILD_VOICE)
        payload.put("video_quality_mode", video_quality_mode)
        payload.put("bitrate", bitrate)
        payload.put("position", position)
        payload.put("user_limit", user_limit)
        payload.put_snowflake("parent_id", parent_id)
        payload.put("rtc_region", region, conversion=str)

        payload.put_array(
            "permission_overwrites",
            permission_overwrites,
            conversion=self._entity_factory.serialize_permission_overwrite,
        )

        self._channels.append(payload)
        return snowflake_id

    def add_stage_channel(
        self,
        name: str,
        /,
        *,
        parent_id: undefined.UndefinedOr[snowflakes.Snowflake] = undefined.UNDEFINED,
        bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Collection[channels.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        region: undefined.UndefinedNoneOr[typing.Union[voices.VoiceRegion, str]],
        user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    ) -> snowflakes.Snowflake:
        snowflake_id = self._new_snowflake()
        payload = data_binding.JSONObjectBuilder()
        payload.put_snowflake("id", snowflake_id)
        payload.put("name", name)
        payload.put("type", channels.ChannelType.GUILD_STAGE)
        payload.put("bitrate", bitrate)
        payload.put("position", position)
        payload.put("user_limit", user_limit)
        payload.put_snowflake("parent_id", parent_id)
        payload.put("rtc_region", region, conversion=str)

        payload.put_array(
            "permission_overwrites",
            permission_overwrites,
            conversion=self._entity_factory.serialize_permission_overwrite,
        )

        self._channels.append(payload)
        return snowflake_id

    def _new_snowflake(self) -> snowflakes.Snowflake:
        value = self._counter
        self._counter += 1
        return snowflakes.Snowflake.from_data(time.utc_datetime(), 0, 0, value)

Result type of hikari.api.rest.RESTClient.guild_builder.

This is used to create a guild in a tidy way using the HTTP API, since the logic behind creating a guild on an API level is somewhat confusing and detailed.

Note: This is a helper class that is used by hikari.api.rest.RESTClient. You should only ever need to use instances of this class that are produced by that API, thus, any details about the constructor are omitted from the following examples for brevity.

Examples

Creating an empty guild.

guild = await rest.guild_builder("My Server!").create()

Creating a guild with an icon

from hikari.files import WebResourceStream

guild_builder = rest.guild_builder("My Server!")
guild_builder.icon = WebResourceStream("cat.png", "http://...")
guild = await guild_builder.create()

Adding roles to your guild.

from hikari.permissions import Permissions

guild_builder = rest.guild_builder("My Server!")

everyone_role_id = guild_builder.add_role("@everyone")
admin_role_id = guild_builder.add_role("Admins", permissions=Permissions.ADMINISTRATOR)

await guild_builder.create()

Warning: The first role must always be the @everyone role.

Note: If you call add_role, the default roles provided by Discord will be created. This also applies to the add_ functions for text channels/voice channels/categories.

Note: Functions that return a hikari.snowflakes.Snowflake do not provide the final ID that the object will have once the API call is made. The returned IDs are only able to be used to re-reference particular objects while building the guild format.

This is provided to allow creation of channels within categories, and to provide permission overwrites.

Adding a text channel to your guild.

guild_builder = rest.guild_builder("My Server!")

category_id = guild_builder.add_category("My safe place")
channel_id = guild_builder.add_text_channel("general", parent_id=category_id)

await guild_builder.create()
Variables and properties
#  icon: Union[hikari.files.Resource[Any], os.PathLike[str], str, bytes, bytearray, memoryview, _io.BytesIO, _io.StringIO, hikari.undefined.UndefinedType]
#  name: str

Name of the guild to create.

Methods
#  def __init__(
   self,
   *,
   entity_factory: hikari.api.entity_factory.EntityFactory,
   executor: Optional[concurrent.futures._base.Executor],
   name: str,
   request_call: Callable[..., Coroutine[NoneType, NoneType, Union[NoneType, Dict[str, Any], List[Any]]]],
   default_message_notifications: Union[hikari.guilds.GuildMessageNotificationsLevel, hikari.undefined.UndefinedType] = UNDEFINED,
   explicit_content_filter_level: Union[hikari.guilds.GuildExplicitContentFilterLevel, hikari.undefined.UndefinedType] = UNDEFINED,
   icon: Union[hikari.files.Resource[Any], os.PathLike[str], str, bytes, bytearray, memoryview, _io.BytesIO, _io.StringIO, hikari.undefined.UndefinedType] = UNDEFINED,
   verification_level: Union[hikari.guilds.GuildVerificationLevel, int, hikari.undefined.UndefinedType] = UNDEFINED
):
View Source
def __init__(self, *, entity_factory, executor, name, request_call, default_message_notifications=attr_dict['default_message_notifications'].default, explicit_content_filter_level=attr_dict['explicit_content_filter_level'].default, icon=attr_dict['icon'].default, verification_level=attr_dict['verification_level'].default):
    self._entity_factory = entity_factory
    self._executor = executor
    self._name = name
    self._request_call = request_call
    self.default_message_notifications = default_message_notifications
    self.explicit_content_filter_level = explicit_content_filter_level
    self.icon = icon
    self.verification_level = verification_level
    self._channels = __attr_factory__channels()
    self._counter = attr_dict['_counter'].default
    self._roles = __attr_factory__roles()

Method generated by attrs for class GuildBuilder.

#  def add_category(
   self,
   name: str,
   /,
   *,
   position: Union[int, hikari.undefined.UndefinedType] = UNDEFINED,
   permission_overwrites: Union[Collection[hikari.channels.PermissionOverwrite], hikari.undefined.UndefinedType] = UNDEFINED,
   nsfw: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED
) -> hikari.snowflakes.Snowflake:
View Source
    def add_category(
        self,
        name: str,
        /,
        *,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Collection[channels.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> snowflakes.Snowflake:
        snowflake_id = self._new_snowflake()
        payload = data_binding.JSONObjectBuilder()
        payload.put_snowflake("id", snowflake_id)
        payload.put("name", name)
        payload.put("type", channels.ChannelType.GUILD_CATEGORY)
        payload.put("position", position)
        payload.put("nsfw", nsfw)

        payload.put_array(
            "permission_overwrites",
            permission_overwrites,
            conversion=self._entity_factory.serialize_permission_overwrite,
        )

        self._channels.append(payload)
        return snowflake_id

Create a category channel.

Parameters
  • name (str): The channels name. Must be between 2 and 1000 characters.
Other Parameters
Returns
  • hikari.snowflakes.Snowflake: The dummy ID for this channel that can be used temporarily to refer to this object while designing the guild layout.

When the guild is created, this will be replaced with a different ID.

#  def add_role(
   self,
   name: str,
   /,
   *,
   color: Union[hikari.colors.Color, SupportsInt, Tuple[SupportsInt, SupportsInt, SupportsInt], Tuple[SupportsFloat, SupportsFloat, SupportsFloat], Sequence[SupportsInt], Sequence[SupportsFloat], str, hikari.undefined.UndefinedType] = UNDEFINED,
   colour: Union[hikari.colors.Color, SupportsInt, Tuple[SupportsInt, SupportsInt, SupportsInt], Tuple[SupportsFloat, SupportsFloat, SupportsFloat], Sequence[SupportsInt], Sequence[SupportsFloat], str, hikari.undefined.UndefinedType] = UNDEFINED,
   hoist: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED,
   mentionable: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED,
   permissions: Union[hikari.permissions.Permissions, hikari.undefined.UndefinedType] = UNDEFINED,
   position: Union[int, hikari.undefined.UndefinedType] = UNDEFINED
) -> hikari.snowflakes.Snowflake:
View Source
    def add_role(
        self,
        name: str,
        /,
        *,
        color: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
        colour: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
        hoist: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        mentionable: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        permissions: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    ) -> snowflakes.Snowflake:
        if not undefined.any_undefined(color, colour):
            raise TypeError("Cannot specify 'color' and 'colour' together.")

        if len(self._roles) == 0:
            if name != "@everyone":
                raise ValueError("First role must always be the '@everyone' role")
            if not undefined.all_undefined(color, colour, hoist, mentionable, position):
                raise ValueError(
                    "Cannot pass 'color', 'colour', 'hoist', 'mentionable' nor 'position' to the '@everyone' role."
                )

        snowflake_id = self._new_snowflake()
        payload = data_binding.JSONObjectBuilder()
        payload.put_snowflake("id", snowflake_id)
        payload.put("name", name)
        payload.put("color", color, conversion=colors.Color.of)
        payload.put("color", colour, conversion=colors.Color.of)
        payload.put("hoist", hoist)
        payload.put("mentionable", mentionable)
        payload.put("permissions", permissions)
        payload.put("position", position)
        self._roles.append(payload)
        return snowflake_id

Create a role.

Warning: The first role you create must always be the @everyone role.

Parameters
  • name (str): The role's name.
Other Parameters
Returns
  • hikari.snowflakes.Snowflake: The dummy ID for this role that can be used temporarily to refer to this object while designing the guild layout.

When the guild is created, this will be replaced with a different ID.

Raises
  • ValueError: If you are defining the first role, but did not name it @everyone.
  • TypeError: If you specify both color and colour together or if you try to specify color, colour, hoisted, mentionable or position for the @everyone role.
#  def add_stage_channel(
   self,
   name: str,
   /,
   *,
   parent_id: Union[hikari.snowflakes.Snowflake, hikari.undefined.UndefinedType] = UNDEFINED,
   bitrate: Union[int, hikari.undefined.UndefinedType] = UNDEFINED,
   position: Union[int, hikari.undefined.UndefinedType] = UNDEFINED,
   permission_overwrites: Union[Collection[hikari.channels.PermissionOverwrite], hikari.undefined.UndefinedType] = UNDEFINED,
   region: Union[hikari.voices.VoiceRegion, str, hikari.undefined.UndefinedType, NoneType],
   user_limit: Union[int, hikari.undefined.UndefinedType] = UNDEFINED
) -> hikari.snowflakes.Snowflake:
View Source
    def add_stage_channel(
        self,
        name: str,
        /,
        *,
        parent_id: undefined.UndefinedOr[snowflakes.Snowflake] = undefined.UNDEFINED,
        bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Collection[channels.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        region: undefined.UndefinedNoneOr[typing.Union[voices.VoiceRegion, str]],
        user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    ) -> snowflakes.Snowflake:
        snowflake_id = self._new_snowflake()
        payload = data_binding.JSONObjectBuilder()
        payload.put_snowflake("id", snowflake_id)
        payload.put("name", name)
        payload.put("type", channels.ChannelType.GUILD_STAGE)
        payload.put("bitrate", bitrate)
        payload.put("position", position)
        payload.put("user_limit", user_limit)
        payload.put_snowflake("parent_id", parent_id)
        payload.put("rtc_region", region, conversion=str)

        payload.put_array(
            "permission_overwrites",
            permission_overwrites,
            conversion=self._entity_factory.serialize_permission_overwrite,
        )

        self._channels.append(payload)
        return snowflake_id

Create a stage channel.

Parameters
  • name (str): The channels name. Must be between 2 and 1000 characters.
Other Parameters
Returns
  • hikari.snowflakes.Snowflake: The dummy ID for this channel that can be used temporarily to refer to this object while designing the guild layout.

When the guild is created, this will be replaced with a different ID.

#  def add_text_channel(
   self,
   name: str,
   /,
   *,
   parent_id: Union[hikari.snowflakes.Snowflake, hikari.undefined.UndefinedType] = UNDEFINED,
   topic: Union[str, hikari.undefined.UndefinedType] = UNDEFINED,
   rate_limit_per_user: Union[int, float, datetime.timedelta, hikari.undefined.UndefinedType] = UNDEFINED,
   position: Union[int, hikari.undefined.UndefinedType] = UNDEFINED,
   permission_overwrites: Union[Collection[hikari.channels.PermissionOverwrite], hikari.undefined.UndefinedType] = UNDEFINED,
   nsfw: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED
) -> hikari.snowflakes.Snowflake:
View Source
    def add_text_channel(
        self,
        name: str,
        /,
        *,
        parent_id: undefined.UndefinedOr[snowflakes.Snowflake] = undefined.UNDEFINED,
        topic: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Collection[channels.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> snowflakes.Snowflake:
        snowflake_id = self._new_snowflake()
        payload = data_binding.JSONObjectBuilder()
        payload.put_snowflake("id", snowflake_id)
        payload.put("name", name)
        payload.put("type", channels.ChannelType.GUILD_TEXT)
        payload.put("topic", topic)
        payload.put("rate_limit_per_user", rate_limit_per_user, conversion=time.timespan_to_int)
        payload.put("position", position)
        payload.put("nsfw", nsfw)
        payload.put_snowflake("parent_id", parent_id)

        payload.put_array(
            "permission_overwrites",
            permission_overwrites,
            conversion=self._entity_factory.serialize_permission_overwrite,
        )

        self._channels.append(payload)
        return snowflake_id

Create a text channel.

Parameters
  • name (str): The channels name. Must be between 2 and 1000 characters.
Other Parameters
Returns
  • hikari.snowflakes.Snowflake: The dummy ID for this channel that can be used temporarily to refer to this object while designing the guild layout.

When the guild is created, this will be replaced with a different ID.

#  def add_voice_channel(
   self,
   name: str,
   /,
   *,
   parent_id: Union[hikari.snowflakes.Snowflake, hikari.undefined.UndefinedType] = UNDEFINED,
   bitrate: Union[int, hikari.undefined.UndefinedType] = UNDEFINED,
   video_quality_mode: Union[hikari.channels.VideoQualityMode, int, hikari.undefined.UndefinedType] = UNDEFINED,
   position: Union[int, hikari.undefined.UndefinedType] = UNDEFINED,
   permission_overwrites: Union[Collection[hikari.channels.PermissionOverwrite], hikari.undefined.UndefinedType] = UNDEFINED,
   region: Union[hikari.voices.VoiceRegion, str, hikari.undefined.UndefinedType, NoneType],
   user_limit: Union[int, hikari.undefined.UndefinedType] = UNDEFINED
) -> hikari.snowflakes.Snowflake:
View Source
    def add_voice_channel(
        self,
        name: str,
        /,
        *,
        parent_id: undefined.UndefinedOr[snowflakes.Snowflake] = undefined.UNDEFINED,
        bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        video_quality_mode: undefined.UndefinedOr[typing.Union[channels.VideoQualityMode, int]] = undefined.UNDEFINED,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Collection[channels.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        region: undefined.UndefinedNoneOr[typing.Union[voices.VoiceRegion, str]],
        user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    ) -> snowflakes.Snowflake:
        snowflake_id = self._new_snowflake()
        payload = data_binding.JSONObjectBuilder()
        payload.put_snowflake("id", snowflake_id)
        payload.put("name", name)
        payload.put("type", channels.ChannelType.GUILD_VOICE)
        payload.put("video_quality_mode", video_quality_mode)
        payload.put("bitrate", bitrate)
        payload.put("position", position)
        payload.put("user_limit", user_limit)
        payload.put_snowflake("parent_id", parent_id)
        payload.put("rtc_region", region, conversion=str)

        payload.put_array(
            "permission_overwrites",
            permission_overwrites,
            conversion=self._entity_factory.serialize_permission_overwrite,
        )

        self._channels.append(payload)
        return snowflake_id

Create a voice channel.

Parameters
  • name (str): The channels name. Must be between 2 and 1000 characters.
Other Parameters
Returns
  • hikari.snowflakes.Snowflake: The dummy ID for this channel that can be used temporarily to refer to this object while designing the guild layout.

When the guild is created, this will be replaced with a different ID.

#  async def create(self) -> hikari.guilds.RESTGuild:
View Source
    async def create(self) -> guilds.RESTGuild:
        route = routes.POST_GUILDS.compile()
        payload = data_binding.JSONObjectBuilder()
        payload.put("name", self.name)
        payload.put_array("roles", self._roles if self._roles else undefined.UNDEFINED)
        payload.put_array("channels", self._channels if self._channels else undefined.UNDEFINED)
        payload.put("verification_level", self.verification_level)
        payload.put("default_message_notifications", self.default_message_notifications)
        payload.put("explicit_content_filter", self.explicit_content_filter_level)

        if self.icon is not undefined.UNDEFINED:
            icon = files.ensure_resource(self.icon)

            async with icon.stream(executor=self._executor) as stream:
                data_uri = await stream.data_uri()
                payload.put("icon", data_uri)

        response = await self._request_call(route, json=payload)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_rest_guild(response)

Send the request to Discord to create the guild.

The application user will be added to this guild as soon as it is created. All IDs that were provided when building this guild will become invalid and will be replaced with real IDs.

Returns
Raises
#  
@attr_extensions.with_copy
@attr.define(kw_only=False, weakref_slot=False)
class InteractionAutocompleteBuilder(hikari.api.special_endpoints.InteractionAutocompleteBuilder):
View Source
@attr_extensions.with_copy
@attr.define(kw_only=False, weakref_slot=False)
class InteractionAutocompleteBuilder(special_endpoints.InteractionAutocompleteBuilder):
    """Standard implementation of `hikari.api.special_endpoints.InteractionAutocompleteBuilder`."""

    _choices: typing.Sequence[commands.CommandChoice] = attr.field(factory=list)

    @property
    def type(self) -> typing.Literal[base_interactions.ResponseType.AUTOCOMPLETE]:
        return base_interactions.ResponseType.AUTOCOMPLETE

    @property
    def choices(self) -> typing.Sequence[commands.CommandChoice]:
        return self._choices

    def set_choices(
        self: _InteractionAutocompleteBuilderT, choices: typing.Sequence[commands.CommandChoice], /
    ) -> _InteractionAutocompleteBuilderT:
        """Set autocomplete choices.

        Returns
        -------
        InteractionAutocompleteBuilder
            Object of this builder.
        """
        self._choices = choices
        return self

    def build(
        self, _: entity_factory_.EntityFactory, /
    ) -> typing.Tuple[data_binding.JSONObject, typing.Sequence[files.Resource[files.AsyncReader]]]:
        data = {"choices": [{"name": choice.name, "value": choice.value} for choice in self._choices]}
        return {"type": self.type, "data": data}, ()
Variables and properties

Return autocomplete choices.

#  type: Literal[<ResponseType.AUTOCOMPLETE: 8>]

Type of this response.

Methods
#  def __init__(self, choices: Sequence[hikari.commands.CommandChoice] = NOTHING):
View Source
def __init__(self, choices=NOTHING):
    if choices is not NOTHING:
        self._choices = choices
    else:
        self._choices = __attr_factory__choices()

Method generated by attrs for class InteractionAutocompleteBuilder.

#  def build(
   self,
   _: hikari.api.entity_factory.EntityFactory,
   /
) -> Tuple[Dict[str, Any], Sequence[hikari.files.Resource[hikari.files.AsyncReader]]]:
View Source
    def build(
        self, _: entity_factory_.EntityFactory, /
    ) -> typing.Tuple[data_binding.JSONObject, typing.Sequence[files.Resource[files.AsyncReader]]]:
        data = {"choices": [{"name": choice.name, "value": choice.value} for choice in self._choices]}
        return {"type": self.type, "data": data}, ()

Build a JSON object from this builder.

Parameters
Returns
  • typing.Tuple[hikari.internal.data_binding.JSONObject, typing.Sequence[files.Resource[Files.AsyncReader]]: A tuple of the built json object representation of this builder and a sequence of up to 10 files to send with the response.
#  def set_choices(
   self: ~_InteractionAutocompleteBuilderT,
   choices: Sequence[hikari.commands.CommandChoice],
   /
) -> ~_InteractionAutocompleteBuilderT:
View Source
    def set_choices(
        self: _InteractionAutocompleteBuilderT, choices: typing.Sequence[commands.CommandChoice], /
    ) -> _InteractionAutocompleteBuilderT:
        """Set autocomplete choices.

        Returns
        -------
        InteractionAutocompleteBuilder
            Object of this builder.
        """
        self._choices = choices
        return self

Set autocomplete choices.

Returns
  • InteractionAutocompleteBuilder: Object of this builder.
#  
@attr_extensions.with_copy
@attr.define(kw_only=False, weakref_slot=False)
class InteractionDeferredBuilder(hikari.api.special_endpoints.InteractionDeferredBuilder):
View Source
@attr_extensions.with_copy
@attr.define(kw_only=False, weakref_slot=False)
class InteractionDeferredBuilder(special_endpoints.InteractionDeferredBuilder):
    """Standard implementation of `hikari.api.special_endpoints.InteractionDeferredBuilder`.

    Parameters
    ----------
    type : hikari.interactions.base_interactions.DeferredResponseTypesT
        The type of interaction response this is.
    """

    # Required arguments.
    _type: base_interactions.DeferredResponseTypesT = attr.field(
        converter=base_interactions.ResponseType,
        validator=attr.validators.in_(base_interactions.DEFERRED_RESPONSE_TYPES),
    )

    _flags: typing.Union[undefined.UndefinedType, int, messages.MessageFlag] = attr.field(
        default=undefined.UNDEFINED, kw_only=True
    )

    @property
    def type(self) -> base_interactions.DeferredResponseTypesT:
        return self._type

    @property
    def flags(self) -> typing.Union[undefined.UndefinedType, int, messages.MessageFlag]:
        return self._flags

    def set_flags(
        self: _InteractionDeferredBuilderT, flags: typing.Union[undefined.UndefinedType, int, messages.MessageFlag], /
    ) -> _InteractionDeferredBuilderT:
        self._flags = flags
        return self

    def build(
        self, _: entity_factory_.EntityFactory, /
    ) -> typing.Tuple[data_binding.JSONObject, typing.Sequence[files.Resource[files.AsyncReader]]]:
        if self._flags is not undefined.UNDEFINED:
            return {"type": self._type, "data": {"flags": self._flags}}, ()

        return {"type": self._type}, ()

Standard implementation of hikari.api.special_endpoints.InteractionDeferredBuilder.

Parameters
Variables and properties

Message flags this response should have.

Note: As of writing the only message flag which can be set here is hikari.messages.MessageFlag.EPHEMERAL.

#  type: Literal[<ResponseType.DEFERRED_MESSAGE_CREATE: 5>, 5, <ResponseType.DEFERRED_MESSAGE_UPDATE: 6>, 6]

Type of this response.

Methods
#  def __init__(
   self,
   type: Any,
   *,
   flags: Union[hikari.undefined.UndefinedType, int, hikari.messages.MessageFlag] = UNDEFINED
):
View Source
def __init__(self, type, *, flags=attr_dict['_flags'].default):
    _setattr = _cached_setattr.__get__(self, self.__class__)
    _setattr('_type', __attr_converter__type(type))
    _setattr('_flags', flags)
    if _config._run_validators is True:
        __attr_validator__type(self, __attr__type, self._type)

Method generated by attrs for class InteractionDeferredBuilder.

#  def build(
   self,
   _: hikari.api.entity_factory.EntityFactory,
   /
) -> Tuple[Dict[str, Any], Sequence[hikari.files.Resource[hikari.files.AsyncReader]]]:
View Source
    def build(
        self, _: entity_factory_.EntityFactory, /
    ) -> typing.Tuple[data_binding.JSONObject, typing.Sequence[files.Resource[files.AsyncReader]]]:
        if self._flags is not undefined.UNDEFINED:
            return {"type": self._type, "data": {"flags": self._flags}}, ()

        return {"type": self._type}, ()

Build a JSON object from this builder.

Parameters
Returns
  • typing.Tuple[hikari.internal.data_binding.JSONObject, typing.Sequence[files.Resource[Files.AsyncReader]]: A tuple of the built json object representation of this builder and a sequence of up to 10 files to send with the response.
#  def set_flags(
   self: ~_InteractionDeferredBuilderT,
   flags: Union[hikari.undefined.UndefinedType, int, hikari.messages.MessageFlag],
   /
) -> ~_InteractionDeferredBuilderT:
View Source
    def set_flags(
        self: _InteractionDeferredBuilderT, flags: typing.Union[undefined.UndefinedType, int, messages.MessageFlag], /
    ) -> _InteractionDeferredBuilderT:
        self._flags = flags
        return self

Set message flags for this response.

Note: As of writing, the only message flag which can be set is hikari.messages.MessageFlag.EPHEMERAL.

Parameters
Returns
  • InteractionMessageBuilder: Object of this builder.
#  
@attr_extensions.with_copy
@attr.define(kw_only=False, weakref_slot=False)
class InteractionMessageBuilder(hikari.api.special_endpoints.InteractionMessageBuilder):
View Source
@attr_extensions.with_copy
@attr.define(kw_only=False, weakref_slot=False)
class InteractionMessageBuilder(special_endpoints.InteractionMessageBuilder):
    """Standard implementation of `hikari.api.special_endpoints.InteractionMessageBuilder`.

    Parameters
    ----------
    type : hikari.interactions.base_interactions.MessageResponseTypesT
        The type of interaction response this is.

    Other Parameters
    ----------------
    content : hikari.undefined.UndefinedOr[str]
        The content of this response, if supplied. This follows the same rules
        as "content" on create message.
    """

    # Required arguments.
    _type: base_interactions.MessageResponseTypesT = attr.field(
        converter=base_interactions.ResponseType,
        validator=attr.validators.in_(base_interactions.MESSAGE_RESPONSE_TYPES),
    )

    # Not-required arguments.
    _content: undefined.UndefinedOr[str] = attr.field(default=undefined.UNDEFINED)

    # Key-word only not-required arguments.
    _flags: typing.Union[int, messages.MessageFlag, undefined.UndefinedType] = attr.field(
        default=undefined.UNDEFINED, kw_only=True
    )
    _is_tts: undefined.UndefinedOr[bool] = attr.field(default=undefined.UNDEFINED, kw_only=True)
    _mentions_everyone: undefined.UndefinedOr[bool] = attr.field(default=undefined.UNDEFINED, kw_only=True)
    _role_mentions: undefined.UndefinedOr[
        typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
    ] = attr.field(default=undefined.UNDEFINED, kw_only=True)
    _user_mentions: undefined.UndefinedOr[
        typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
    ] = attr.field(default=undefined.UNDEFINED, kw_only=True)
    _attachments: undefined.UndefinedOr[typing.List[files.Resourceish]] = attr.field(
        default=undefined.UNDEFINED, kw_only=True
    )
    _components: undefined.UndefinedOr[typing.List[special_endpoints.ComponentBuilder]] = attr.field(
        default=undefined.UNDEFINED, kw_only=True
    )
    _embeds: undefined.UndefinedOr[typing.List[embeds_.Embed]] = attr.field(default=undefined.UNDEFINED, kw_only=True)

    @property
    def attachments(self) -> undefined.UndefinedOr[typing.Sequence[files.Resourceish]]:
        return self._attachments.copy() if self._attachments is not undefined.UNDEFINED else undefined.UNDEFINED

    @property
    def content(self) -> undefined.UndefinedOr[str]:
        return self._content

    @property
    def components(self) -> undefined.UndefinedOr[typing.Sequence[special_endpoints.ComponentBuilder]]:
        return self._components.copy() if self._components is not undefined.UNDEFINED else undefined.UNDEFINED

    @property
    def embeds(self) -> undefined.UndefinedOr[typing.Sequence[embeds_.Embed]]:
        return self._embeds.copy() if self._embeds is not undefined.UNDEFINED else undefined.UNDEFINED

    @property
    def flags(self) -> typing.Union[undefined.UndefinedType, int, messages.MessageFlag]:
        return self._flags

    @property
    def is_tts(self) -> undefined.UndefinedOr[bool]:
        return self._is_tts

    @property
    def mentions_everyone(self) -> undefined.UndefinedOr[bool]:
        return self._mentions_everyone

    @property
    def role_mentions(
        self,
    ) -> undefined.UndefinedOr[typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]]:
        return self._role_mentions

    @property
    def type(self) -> base_interactions.MessageResponseTypesT:
        return self._type

    @property
    def user_mentions(
        self,
    ) -> undefined.UndefinedOr[typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]]:
        return self._user_mentions

    def add_attachment(
        self: _InteractionMessageBuilderT, attachment: files.Resourceish, /
    ) -> _InteractionMessageBuilderT:
        if self._attachments is undefined.UNDEFINED:
            self._attachments = []

        self._attachments.append(attachment)
        return self

    def add_component(
        self: _InteractionMessageBuilderT, component: special_endpoints.ComponentBuilder, /
    ) -> _InteractionMessageBuilderT:
        if self._components is undefined.UNDEFINED:
            self._components = []

        self._components.append(component)
        return self

    def add_embed(self: _InteractionMessageBuilderT, embed: embeds_.Embed, /) -> _InteractionMessageBuilderT:
        if self._embeds is undefined.UNDEFINED:
            self._embeds = []

        self._embeds.append(embed)
        return self

    def set_content(
        self: _InteractionMessageBuilderT, content: undefined.UndefinedOr[str], /
    ) -> _InteractionMessageBuilderT:
        self._content = str(content) if content is not undefined.UNDEFINED else undefined.UNDEFINED
        return self

    def set_flags(
        self: _InteractionMessageBuilderT, flags: typing.Union[undefined.UndefinedType, int, messages.MessageFlag], /
    ) -> _InteractionMessageBuilderT:
        self._flags = flags
        return self

    def set_tts(self: _InteractionMessageBuilderT, tts: undefined.UndefinedOr[bool], /) -> _InteractionMessageBuilderT:
        self._is_tts = tts
        return self

    def set_mentions_everyone(
        self: _InteractionMessageBuilderT, state: undefined.UndefinedOr[bool] = undefined.UNDEFINED, /
    ) -> _InteractionMessageBuilderT:
        self._mentions_everyone = state
        return self

    def set_role_mentions(
        self: _InteractionMessageBuilderT,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
        /,
    ) -> _InteractionMessageBuilderT:
        self._role_mentions = role_mentions
        return self

    def set_user_mentions(
        self: _InteractionMessageBuilderT,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        /,
    ) -> _InteractionMessageBuilderT:
        self._user_mentions = user_mentions
        return self

    def build(
        self, entity_factory: entity_factory_.EntityFactory, /
    ) -> typing.Tuple[data_binding.JSONObject, typing.Sequence[files.Resource[files.AsyncReader]]]:
        data = data_binding.JSONObjectBuilder()
        data.put("content", self.content)

        if self._attachments:
            final_attachments = [files.ensure_resource(attachment) for attachment in self._attachments]

        else:
            final_attachments = []

        if self._embeds is not undefined.UNDEFINED:
            embeds: typing.List[data_binding.JSONObject] = []
            for embed, attachments in map(entity_factory.serialize_embed, self._embeds):
                final_attachments.extend(attachments)
                embeds.append(embed)

            data["embeds"] = embeds

        data.put_array("components", self._components, conversion=lambda component: component.build())
        data.put("flags", self.flags)
        data.put("tts", self.is_tts)

        if (
            not undefined.all_undefined(self.mentions_everyone, self.user_mentions, self.role_mentions)
            or self.type is base_interactions.ResponseType.MESSAGE_CREATE
        ):
            data["allowed_mentions"] = mentions.generate_allowed_mentions(
                self.mentions_everyone, undefined.UNDEFINED, self.user_mentions, self.role_mentions
            )

        return {"type": self._type, "data": data}, final_attachments

Standard implementation of hikari.api.special_endpoints.InteractionMessageBuilder.

Parameters
Other Parameters
  • content (hikari.undefined.UndefinedOr[str]): The content of this response, if supplied. This follows the same rules as "content" on create message.
Variables and properties
#  attachments: Union[Sequence[Union[hikari.files.Resource[Any], os.PathLike[str], str, bytes, bytearray, memoryview, _io.BytesIO, _io.StringIO]], hikari.undefined.UndefinedType]

Sequence of up to 10 attachments to send with the message.

Sequence of up to 5 component builders to send in this response.

Response's message content.

Sequence of up to 10 of the embeds included in this response.

Message flags this response should have.

Note: As of writing the only message flag which can be set here is hikari.messages.MessageFlag.EPHEMERAL.

Whether this response's content should be treated as text-to-speech.

If left as hikari.undefined.UNDEFINED then this will be disabled.

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

Whether @everyone and @here mentions should be enabled for this response.

If left as hikari.undefined.UNDEFINED then they will be disabled.

Whether and what role mentions should be enabled for this response.

Either a sequence of object/IDs of the roles mentions should be enabled for, False or hikari.undefined.UNDEFINED to disallow any role mentions or True to allow all role mentions.

#  type: Literal[<ResponseType.MESSAGE_CREATE: 4>, 4, <ResponseType.MESSAGE_UPDATE: 7>, 7]

Type of this response.

Whether and what user mentions should be enabled for this response.

Either a sequence of object/IDs of the users mentions should be enabled for, False or hikari.undefined.UNDEFINED to disallow any user mentions or True to allow all user mentions.

Methods
#  def __init__(
   self,
   type: Any,
   content: Union[str, hikari.undefined.UndefinedType] = UNDEFINED,
   *,
   flags: Union[int, hikari.messages.MessageFlag, hikari.undefined.UndefinedType] = UNDEFINED,
   is_tts: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED,
   mentions_everyone: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED,
   role_mentions: Union[Sequence[Union[hikari.guilds.PartialRole, hikari.snowflakes.Snowflake, int]], bool, hikari.undefined.UndefinedType] = UNDEFINED,
   user_mentions: Union[Sequence[Union[hikari.users.PartialUser, hikari.snowflakes.Snowflake, int]], bool, hikari.undefined.UndefinedType] = UNDEFINED,
   attachments: Union[List[Union[hikari.files.Resource[Any], os.PathLike[str], str, bytes, bytearray, memoryview, _io.BytesIO, _io.StringIO]], hikari.undefined.UndefinedType] = UNDEFINED,
   components: Union[List[hikari.api.special_endpoints.ComponentBuilder], hikari.undefined.UndefinedType] = UNDEFINED,
   embeds: Union[List[hikari.embeds.Embed], hikari.undefined.UndefinedType] = UNDEFINED
):
View Source
def __init__(self, type, content=attr_dict['_content'].default, *, flags=attr_dict['_flags'].default, is_tts=attr_dict['_is_tts'].default, mentions_everyone=attr_dict['_mentions_everyone'].default, role_mentions=attr_dict['_role_mentions'].default, user_mentions=attr_dict['_user_mentions'].default, attachments=attr_dict['_attachments'].default, components=attr_dict['_components'].default, embeds=attr_dict['_embeds'].default):
    _setattr = _cached_setattr.__get__(self, self.__class__)
    _setattr('_type', __attr_converter__type(type))
    _setattr('_content', content)
    _setattr('_flags', flags)
    _setattr('_is_tts', is_tts)
    _setattr('_mentions_everyone', mentions_everyone)
    _setattr('_role_mentions', role_mentions)
    _setattr('_user_mentions', user_mentions)
    _setattr('_attachments', attachments)
    _setattr('_components', components)
    _setattr('_embeds', embeds)
    if _config._run_validators is True:
        __attr_validator__type(self, __attr__type, self._type)

Method generated by attrs for class InteractionMessageBuilder.

#  def add_attachment(
   self: ~_InteractionMessageBuilderT,
   attachment: Union[hikari.files.Resource[Any], os.PathLike[str], str, bytes, bytearray, memoryview, _io.BytesIO, _io.StringIO],
   /
) -> ~_InteractionMessageBuilderT:
View Source
    def add_attachment(
        self: _InteractionMessageBuilderT, attachment: files.Resourceish, /
    ) -> _InteractionMessageBuilderT:
        if self._attachments is undefined.UNDEFINED:
            self._attachments = []

        self._attachments.append(attachment)
        return self

Add an attachment to this response.

Parameters
Returns
  • InteractionMessageBuilder: Object of this builder.
#  def add_component(
   self: ~_InteractionMessageBuilderT,
   component: hikari.api.special_endpoints.ComponentBuilder,
   /
) -> ~_InteractionMessageBuilderT:
View Source
    def add_component(
        self: _InteractionMessageBuilderT, component: special_endpoints.ComponentBuilder, /
    ) -> _InteractionMessageBuilderT:
        if self._components is undefined.UNDEFINED:
            self._components = []

        self._components.append(component)
        return self

Add a component to this response.

Parameters
  • component (ComponentBuilder): The component builder to add to this response.
Returns
  • InteractionMessageBuilder: Object of this builder.
#  def add_embed(
   self: ~_InteractionMessageBuilderT,
   embed: hikari.embeds.Embed,
   /
) -> ~_InteractionMessageBuilderT:
View Source
    def add_embed(self: _InteractionMessageBuilderT, embed: embeds_.Embed, /) -> _InteractionMessageBuilderT:
        if self._embeds is undefined.UNDEFINED:
            self._embeds = []

        self._embeds.append(embed)
        return self

Add an embed to this response.

Parameters
Returns
  • InteractionMessageBuilder: Object of this builder to allow for chained calls.
#  def build(
   self,
   entity_factory: hikari.api.entity_factory.EntityFactory,
   /
) -> Tuple[Dict[str, Any], Sequence[hikari.files.Resource[hikari.files.AsyncReader]]]:
View Source
    def build(
        self, entity_factory: entity_factory_.EntityFactory, /
    ) -> typing.Tuple[data_binding.JSONObject, typing.Sequence[files.Resource[files.AsyncReader]]]:
        data = data_binding.JSONObjectBuilder()
        data.put("content", self.content)

        if self._attachments:
            final_attachments = [files.ensure_resource(attachment) for attachment in self._attachments]

        else:
            final_attachments = []

        if self._embeds is not undefined.UNDEFINED:
            embeds: typing.List[data_binding.JSONObject] = []
            for embed, attachments in map(entity_factory.serialize_embed, self._embeds):
                final_attachments.extend(attachments)
                embeds.append(embed)

            data["embeds"] = embeds

        data.put_array("components", self._components, conversion=lambda component: component.build())
        data.put("flags", self.flags)
        data.put("tts", self.is_tts)

        if (
            not undefined.all_undefined(self.mentions_everyone, self.user_mentions, self.role_mentions)
            or self.type is base_interactions.ResponseType.MESSAGE_CREATE
        ):
            data["allowed_mentions"] = mentions.generate_allowed_mentions(
                self.mentions_everyone, undefined.UNDEFINED, self.user_mentions, self.role_mentions
            )

        return {"type": self._type, "data": data}, final_attachments

Build a JSON object from this builder.

Parameters
Returns
  • typing.Tuple[hikari.internal.data_binding.JSONObject, typing.Sequence[files.Resource[Files.AsyncReader]]: A tuple of the built json object representation of this builder and a sequence of up to 10 files to send with the response.
#  def set_content(
   self: ~_InteractionMessageBuilderT,
   content: Union[str, hikari.undefined.UndefinedType],
   /
) -> ~_InteractionMessageBuilderT:
View Source
    def set_content(
        self: _InteractionMessageBuilderT, content: undefined.UndefinedOr[str], /
    ) -> _InteractionMessageBuilderT:
        self._content = str(content) if content is not undefined.UNDEFINED else undefined.UNDEFINED
        return self

Set the response's message content.

Parameters
Returns
  • InteractionMessageBuilder: Object of this builder to allow for chained calls.
#  def set_flags(
   self: ~_InteractionMessageBuilderT,
   flags: Union[hikari.undefined.UndefinedType, int, hikari.messages.MessageFlag],
   /
) -> ~_InteractionMessageBuilderT:
View Source
    def set_flags(
        self: _InteractionMessageBuilderT, flags: typing.Union[undefined.UndefinedType, int, messages.MessageFlag], /
    ) -> _InteractionMessageBuilderT:
        self._flags = flags
        return self

Set message flags for this response.

Note: As of writing, the only message flag which can be set is hikari.messages.MessageFlag.EPHEMERAL..

Parameters
Returns
  • InteractionMessageBuilder: Object of this builder to allow for chained calls.
#  def set_mentions_everyone(
   self: ~_InteractionMessageBuilderT,
   state: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED,
   /
) -> ~_InteractionMessageBuilderT:
View Source
    def set_mentions_everyone(
        self: _InteractionMessageBuilderT, state: undefined.UndefinedOr[bool] = undefined.UNDEFINED, /
    ) -> _InteractionMessageBuilderT:
        self._mentions_everyone = state
        return self

Set whether this response should be able to mention @everyone/@here.

Parameters
Returns
  • InteractionMessageBuilder: Object of this builder to allow for chained calls.
#  def set_role_mentions(
   self: ~_InteractionMessageBuilderT,
   role_mentions: Union[Sequence[Union[hikari.guilds.PartialRole, hikari.snowflakes.Snowflake, int]], bool, hikari.undefined.UndefinedType] = UNDEFINED,
   /
) -> ~_InteractionMessageBuilderT:
View Source
    def set_role_mentions(
        self: _InteractionMessageBuilderT,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
        /,
    ) -> _InteractionMessageBuilderT:
        self._role_mentions = role_mentions
        return self

Set whether and what role mentions should be possible for this response.

Parameters
Returns
  • InteractionMessageBuilder: Object of this builder to allow for chained calls.
#  def set_tts(
   self: ~_InteractionMessageBuilderT,
   tts: Union[bool, hikari.undefined.UndefinedType],
   /
) -> ~_InteractionMessageBuilderT:
View Source
    def set_tts(self: _InteractionMessageBuilderT, tts: undefined.UndefinedOr[bool], /) -> _InteractionMessageBuilderT:
        self._is_tts = tts
        return self

Set whether this response should trigger text-to-speech processing.

Parameters
  • tts (Whether this response should trigger text-to-speech processing.):
Returns
  • InteractionMessageBuilder: Object of this builder to allow for chained calls.
#  def set_user_mentions(
   self: ~_InteractionMessageBuilderT,
   user_mentions: Union[Sequence[Union[hikari.users.PartialUser, hikari.snowflakes.Snowflake, int]], bool, hikari.undefined.UndefinedType] = UNDEFINED,
   /
) -> ~_InteractionMessageBuilderT:
View Source
    def set_user_mentions(
        self: _InteractionMessageBuilderT,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        /,
    ) -> _InteractionMessageBuilderT:
        self._user_mentions = user_mentions
        return self

Set whether and what user mentions should be possible for this response.

Parameters
Returns
  • InteractionMessageBuilder: Object of this builder to allow for chained calls.
View Source
@attr.define(kw_only=True, weakref_slot=False)
class InteractiveButtonBuilder(
    _ButtonBuilder[_ContainerProtoT], special_endpoints.InteractiveButtonBuilder[_ContainerProtoT]
):
    """Builder class for interactive buttons."""

    _custom_id: str = attr.field()

    @property
    def custom_id(self) -> str:
        return self._custom_id

Builder class for interactive buttons.

Variables and properties
#  custom_id: str

Developer set custom ID used for identifying interactions with this button.

Emoji which should appear on this button.

This can be the object, ID or raw string of the emoji.

#  is_disabled: bool

Whether the button should be marked as disabled.

Defaults to False.

Text label which should appear on this button.

Note: The text label to that should appear on this button. This may be up to 80 characters long.

Button's style.

Methods
#  def __init__(
   self,
   *,
   container: ~_ContainerProtoT,
   style: Union[int, hikari.messages.ButtonStyle],
   url: Union[str, hikari.undefined.UndefinedType] = UNDEFINED,
   emoji: Union[hikari.snowflakes.Snowflake, int, hikari.emojis.Emoji, str, hikari.undefined.UndefinedType] = UNDEFINED,
   emoji_id: Union[str, hikari.undefined.UndefinedType] = UNDEFINED,
   emoji_name: Union[str, hikari.undefined.UndefinedType] = UNDEFINED,
   label: Union[str, hikari.undefined.UndefinedType] = UNDEFINED,
   is_disabled: bool = False,
   custom_id: str
):
View Source
def __init__(self, *, container, style, url=attr_dict['_url'].default, emoji=attr_dict['_emoji'].default, emoji_id=attr_dict['_emoji_id'].default, emoji_name=attr_dict['_emoji_name'].default, label=attr_dict['_label'].default, is_disabled=attr_dict['_is_disabled'].default, custom_id):
    self._container = container
    self._style = style
    self._url = url
    self._emoji = emoji
    self._emoji_id = emoji_id
    self._emoji_name = emoji_name
    self._label = label
    self._is_disabled = is_disabled
    self._custom_id = custom_id

Method generated by attrs for class InteractiveButtonBuilder.

#  def add_to_container(self) -> ~_ContainerProtoT:
View Source
    def add_to_container(self) -> _ContainerProtoT:
        self._container.add_component(self)
        return self._container

Add this button to the container component it belongs to.

This is used as the finalising call during chained calls.

Returns
  • _ContainerT: The container component that owns this button.
#  def build(self) -> Dict[str, Any]:
View Source
    def build(self) -> data_binding.JSONObject:
        data = data_binding.JSONObjectBuilder()

        data["type"] = messages.ComponentType.BUTTON
        data["style"] = self._style
        data["disabled"] = self._is_disabled
        data.put("label", self._label)

        if self._emoji_id is not undefined.UNDEFINED:
            data["emoji"] = {"id": self._emoji_id}

        elif self._emoji_name is not undefined.UNDEFINED:
            data["emoji"] = {"name": self._emoji_name}

        data.put("custom_id", self._custom_id)
        data.put("url", self._url)

        return data

Build a JSON object from this builder.

Returns
#  def set_emoji(
   self: ~_ButtonBuilderT,
   emoji: Union[hikari.snowflakes.Snowflake, int, hikari.emojis.Emoji, str, hikari.undefined.UndefinedType],
   /
) -> ~_ButtonBuilderT:
View Source
    def set_emoji(
        self: _ButtonBuilderT,
        emoji: typing.Union[snowflakes.Snowflakeish, emojis.Emoji, str, undefined.UndefinedType],
        /,
    ) -> _ButtonBuilderT:
        self._emoji_id, self._emoji_name = _build_emoji(emoji)
        self._emoji = emoji
        return self

Set the emoji to display on this button.

Parameters
Returns
  • ButtonBuilder: The builder object to enable chained calls.
#  def set_is_disabled(self: ~_ButtonBuilderT, state: bool, /) -> ~_ButtonBuilderT:
View Source
    def set_is_disabled(self: _ButtonBuilderT, state: bool, /) -> _ButtonBuilderT:
        self._is_disabled = state
        return self

Set whether this button should be disabled.

Parameters
  • state (bool): Whether this button should be disabled.
Returns
  • ButtonBuilder: The builder object to enable chained calls.
#  def set_label(
   self: ~_ButtonBuilderT,
   label: Union[str, hikari.undefined.UndefinedType],
   /
) -> ~_ButtonBuilderT:
View Source
    def set_label(self: _ButtonBuilderT, label: undefined.UndefinedOr[str], /) -> _ButtonBuilderT:
        self._label = label
        return self

Set the text label which should be displayed on this button.

Parameters
Returns
  • ButtonBuilder: The builder object to enable chained calls.
View Source
@attr.define(kw_only=True, weakref_slot=False)
class LinkButtonBuilder(_ButtonBuilder[_ContainerProtoT], special_endpoints.LinkButtonBuilder[_ContainerProtoT]):
    """Builder class for link buttons."""

    _url: str = attr.field()

    @property
    def url(self) -> str:
        return self._url

Builder class for link buttons.

Variables and properties

Emoji which should appear on this button.

This can be the object, ID or raw string of the emoji.

#  is_disabled: bool

Whether the button should be marked as disabled.

Defaults to False.

Text label which should appear on this button.

Note: The text label to that should appear on this button. This may be up to 80 characters long.

Button's style.

#  url: str

URL this button should link to when pressed.

Methods
#  def __init__(
   self,
   *,
   container: ~_ContainerProtoT,
   style: Union[int, hikari.messages.ButtonStyle],
   custom_id: Union[str, hikari.undefined.UndefinedType] = UNDEFINED,
   emoji: Union[hikari.snowflakes.Snowflake, int, hikari.emojis.Emoji, str, hikari.undefined.UndefinedType] = UNDEFINED,
   emoji_id: Union[str, hikari.undefined.UndefinedType] = UNDEFINED,
   emoji_name: Union[str, hikari.undefined.UndefinedType] = UNDEFINED,
   label: Union[str, hikari.undefined.UndefinedType] = UNDEFINED,
   is_disabled: bool = False,
   url: str
):
View Source
def __init__(self, *, container, style, custom_id=attr_dict['_custom_id'].default, emoji=attr_dict['_emoji'].default, emoji_id=attr_dict['_emoji_id'].default, emoji_name=attr_dict['_emoji_name'].default, label=attr_dict['_label'].default, is_disabled=attr_dict['_is_disabled'].default, url):
    self._container = container
    self._style = style
    self._custom_id = custom_id
    self._emoji = emoji
    self._emoji_id = emoji_id
    self._emoji_name = emoji_name
    self._label = label
    self._is_disabled = is_disabled
    self._url = url

Method generated by attrs for class LinkButtonBuilder.

#  def add_to_container(self) -> ~_ContainerProtoT:
View Source
    def add_to_container(self) -> _ContainerProtoT:
        self._container.add_component(self)
        return self._container

Add this button to the container component it belongs to.

This is used as the finalising call during chained calls.

Returns
  • _ContainerT: The container component that owns this button.
#  def build(self) -> Dict[str, Any]:
View Source
    def build(self) -> data_binding.JSONObject:
        data = data_binding.JSONObjectBuilder()

        data["type"] = messages.ComponentType.BUTTON
        data["style"] = self._style
        data["disabled"] = self._is_disabled
        data.put("label", self._label)

        if self._emoji_id is not undefined.UNDEFINED:
            data["emoji"] = {"id": self._emoji_id}

        elif self._emoji_name is not undefined.UNDEFINED:
            data["emoji"] = {"name": self._emoji_name}

        data.put("custom_id", self._custom_id)
        data.put("url", self._url)

        return data

Build a JSON object from this builder.

Returns
#  def set_emoji(
   self: ~_ButtonBuilderT,
   emoji: Union[hikari.snowflakes.Snowflake, int, hikari.emojis.Emoji, str, hikari.undefined.UndefinedType],
   /
) -> ~_ButtonBuilderT:
View Source
    def set_emoji(
        self: _ButtonBuilderT,
        emoji: typing.Union[snowflakes.Snowflakeish, emojis.Emoji, str, undefined.UndefinedType],
        /,
    ) -> _ButtonBuilderT:
        self._emoji_id, self._emoji_name = _build_emoji(emoji)
        self._emoji = emoji
        return self

Set the emoji to display on this button.

Parameters
Returns
  • ButtonBuilder: The builder object to enable chained calls.
#  def set_is_disabled(self: ~_ButtonBuilderT, state: bool, /) -> ~_ButtonBuilderT:
View Source
    def set_is_disabled(self: _ButtonBuilderT, state: bool, /) -> _ButtonBuilderT:
        self._is_disabled = state
        return self

Set whether this button should be disabled.

Parameters
  • state (bool): Whether this button should be disabled.
Returns
  • ButtonBuilder: The builder object to enable chained calls.
#  def set_label(
   self: ~_ButtonBuilderT,
   label: Union[str, hikari.undefined.UndefinedType],
   /
) -> ~_ButtonBuilderT:
View Source
    def set_label(self: _ButtonBuilderT, label: undefined.UndefinedOr[str], /) -> _ButtonBuilderT:
        self._label = label
        return self

Set the text label which should be displayed on this button.

Parameters
Returns
  • ButtonBuilder: The builder object to enable chained calls.
#  
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
class SelectMenuBuilder(hikari.api.special_endpoints.SelectMenuBuilder[~_ContainerProtoT]):
View Source
@attr_extensions.with_copy
@attr.define(kw_only=True, weakref_slot=False)
class SelectMenuBuilder(special_endpoints.SelectMenuBuilder[_ContainerProtoT]):
    """Builder class for select menus."""

    _container: _ContainerProtoT = attr.field()
    _custom_id: str = attr.field()
    # Any has to be used here as we can't access Self type in this context
    _options: typing.List[special_endpoints.SelectOptionBuilder[typing.Any]] = attr.field(factory=list)
    _placeholder: undefined.UndefinedOr[str] = attr.field(default=undefined.UNDEFINED)
    _min_values: int = attr.field(default=0)
    _max_values: int = attr.field(default=1)
    _is_disabled: bool = attr.field(default=False)

    @property
    def custom_id(self) -> str:
        return self._custom_id

    @property
    def is_disabled(self) -> bool:
        return self._is_disabled

    @property
    def options(
        self: _SelectMenuBuilderT,
    ) -> typing.Sequence[special_endpoints.SelectOptionBuilder[_SelectMenuBuilderT]]:
        return self._options.copy()

    @property
    def placeholder(self) -> undefined.UndefinedOr[str]:
        return self._placeholder

    @property
    def min_values(self) -> int:
        return self._min_values

    @property
    def max_values(self) -> int:
        return self._max_values

    def add_option(
        self: _SelectMenuBuilderT, label: str, value: str, /
    ) -> special_endpoints.SelectOptionBuilder[_SelectMenuBuilderT]:
        return _SelectOptionBuilder(menu=self, label=label, value=value)

    def add_raw_option(
        self: _SelectMenuBuilderT, option: special_endpoints.SelectOptionBuilder[_SelectMenuBuilderT], /
    ) -> _SelectMenuBuilderT:
        self._options.append(option)
        return self

    def set_is_disabled(self: _SelectMenuBuilderT, state: bool, /) -> _SelectMenuBuilderT:
        self._is_disabled = state
        return self

    def set_placeholder(self: _SelectMenuBuilderT, value: undefined.UndefinedOr[str], /) -> _SelectMenuBuilderT:
        self._placeholder = value
        return self

    def set_min_values(self: _SelectMenuBuilderT, value: int, /) -> _SelectMenuBuilderT:
        self._min_values = value
        return self

    def set_max_values(self: _SelectMenuBuilderT, value: int, /) -> _SelectMenuBuilderT:
        self._max_values = value
        return self

    def add_to_container(self) -> _ContainerProtoT:
        self._container.add_component(self)
        return self._container

    def build(self) -> data_binding.JSONObject:
        data = data_binding.JSONObjectBuilder()

        data["type"] = messages.ComponentType.SELECT_MENU
        data["custom_id"] = self._custom_id
        data["options"] = [option.build() for option in self._options]
        data.put("placeholder", self._placeholder)
        data.put("min_values", self._min_values)
        data.put("max_values", self._max_values)
        data.put("disabled", self._is_disabled)
        return data

Builder class for select menus.

Variables and properties
#  custom_id: str

Developer set custom ID used for identifying interactions with this menu.

#  is_disabled: bool

Whether the select menu should be marked as disabled.

Defaults to False.

#  max_values: int

Maximum number of options which can be chosen.

Defaults to 1. Must be greater than or equal to SelectMenuBuilder.min_values and less than or equal to 25.

#  min_values: int

Minimum number of options which must be chosen.

Defaults to 1. Must be less than or equal to SelectMenuBuilder.max_values and greater than or equal to 0.

#  options: Sequence[hikari.api.special_endpoints.SelectOptionBuilder[~_SelectMenuBuilderT]]

Sequence of the options set for this select menu.

#  placeholder: Union[str, hikari.undefined.UndefinedType]

Return the placeholder text to display when no options are selected.

Methods
#  def __init__(
   self,
   *,
   container: ~_ContainerProtoT,
   custom_id: str,
   options: List[hikari.api.special_endpoints.SelectOptionBuilder[Any]] = NOTHING,
   placeholder: Union[str, hikari.undefined.UndefinedType] = UNDEFINED,
   min_values: int = 0,
   max_values: int = 1,
   is_disabled: bool = False
):
View Source
def __init__(self, *, container, custom_id, options=NOTHING, placeholder=attr_dict['_placeholder'].default, min_values=attr_dict['_min_values'].default, max_values=attr_dict['_max_values'].default, is_disabled=attr_dict['_is_disabled'].default):
    self._container = container
    self._custom_id = custom_id
    if options is not NOTHING:
        self._options = options
    else:
        self._options = __attr_factory__options()
    self._placeholder = placeholder
    self._min_values = min_values
    self._max_values = max_values
    self._is_disabled = is_disabled

Method generated by attrs for class SelectMenuBuilder.

#  def add_option(
   self: ~_SelectMenuBuilderT,
   label: str,
   value: str,
   /
) -> hikari.api.special_endpoints.SelectOptionBuilder[~_SelectMenuBuilderT]:
View Source
    def add_option(
        self: _SelectMenuBuilderT, label: str, value: str, /
    ) -> special_endpoints.SelectOptionBuilder[_SelectMenuBuilderT]:
        return _SelectOptionBuilder(menu=self, label=label, value=value)

Add an option to this menu.

Note: Setup should be finalised by calling add_to_menu in the builder returned.

Parameters
  • label (str): The user-facing name of this option, max 100 characters.
  • value (str): The developer defined value of this option, max 100 characters.
Returns
  • SelectOptionBuilder[SelectMenuBuilder]: Option builder object.
#  def add_raw_option(
   self: ~_SelectMenuBuilderT,
   option: hikari.api.special_endpoints.SelectOptionBuilder[~_SelectMenuBuilderT],
   /
) -> ~_SelectMenuBuilderT:
View Source
    def add_raw_option(
        self: _SelectMenuBuilderT, option: special_endpoints.SelectOptionBuilder[_SelectMenuBuilderT], /
    ) -> _SelectMenuBuilderT:
        self._options.append(option)
        return self
#  def add_to_container(self) -> ~_ContainerProtoT:
View Source
    def add_to_container(self) -> _ContainerProtoT:
        self._container.add_component(self)
        return self._container

Finalise this builder by adding it to its parent container component.

Returns
  • _ContainerT: The parent container component builder.
#  def build(self) -> Dict[str, Any]:
View Source
    def build(self) -> data_binding.JSONObject:
        data = data_binding.JSONObjectBuilder()

        data["type"] = messages.ComponentType.SELECT_MENU
        data["custom_id"] = self._custom_id
        data["options"] = [option.build() for option in self._options]
        data.put("placeholder", self._placeholder)
        data.put("min_values", self._min_values)
        data.put("max_values", self._max_values)
        data.put("disabled", self._is_disabled)
        return data

Build a JSON object from this builder.

Returns
#  def set_is_disabled(self: ~_SelectMenuBuilderT, state: bool, /) -> ~_SelectMenuBuilderT:
View Source
    def set_is_disabled(self: _SelectMenuBuilderT, state: bool, /) -> _SelectMenuBuilderT:
        self._is_disabled = state
        return self

Set whether this option is disabled.

Defaults to False.

Parameters
  • state (bool): Whether this option is disabled.
Returns
  • SelectMenuBuilder: The builder object to enable chained calls.
#  def set_max_values(self: ~_SelectMenuBuilderT, value: int, /) -> ~_SelectMenuBuilderT:
View Source
    def set_max_values(self: _SelectMenuBuilderT, value: int, /) -> _SelectMenuBuilderT:
        self._max_values = value
        return self

Set the maximum amount of options which can be selected for this menu.

Note: This defaults to 1 if not set and must be less than or equal to 25 and greater than or equal to SelectMenuBuilder.min_values.

Parameters
  • value (int): The maximum amount of options which can selected for this menu.
Returns
  • SelectMenuBuilder: The builder object to enable chained calls.
#  def set_min_values(self: ~_SelectMenuBuilderT, value: int, /) -> ~_SelectMenuBuilderT:
View Source
    def set_min_values(self: _SelectMenuBuilderT, value: int, /) -> _SelectMenuBuilderT:
        self._min_values = value
        return self

Set the minimum amount of options which need to be selected for this menu.

Note: This defaults to 1 if not set and must be greater than or equal to 0 and less than or equal to SelectMenuBuilder.max_values.

Parameters
  • value (int): The minimum amount of options which need to be selected for this menu.
Returns
  • SelectMenuBuilder: The builder object to enable chained calls.
#  def set_placeholder(
   self: ~_SelectMenuBuilderT,
   value: Union[str, hikari.undefined.UndefinedType],
   /
) -> ~_SelectMenuBuilderT:
View Source
    def set_placeholder(self: _SelectMenuBuilderT, value: undefined.UndefinedOr[str], /) -> _SelectMenuBuilderT:
        self._placeholder = value
        return self

Set place-holder text to be shown when no option is selected.

Parameters
Returns
  • SelectMenuBuilder: The builder object to enable chained calls.
#  
@attr_extensions.with_copy
@attr.define(kw_only=False, weakref_slot=False)
class SlashCommandBuilder(CommandBuilder, hikari.api.special_endpoints.SlashCommandBuilder):
View Source
@attr_extensions.with_copy
@attr.define(kw_only=False, weakref_slot=False)
class SlashCommandBuilder(CommandBuilder, special_endpoints.SlashCommandBuilder):
    """Builder class for slash commands."""

    _description: str = attr.field()
    _options: typing.List[commands.CommandOption] = attr.field(factory=list, kw_only=True)

    @property
    def description(self) -> str:
        return self._description

    @property
    def type(self) -> commands.CommandType:
        return commands.CommandType.SLASH

    def add_option(self: _SlashCommandBuilderT, option: commands.CommandOption) -> _SlashCommandBuilderT:
        self._options.append(option)
        return self

    @property
    def options(self) -> typing.Sequence[commands.CommandOption]:
        return self._options.copy()

    def build(self, entity_factory: entity_factory_.EntityFactory, /) -> data_binding.JSONObjectBuilder:
        data = super().build(entity_factory)
        data.put("description", self._description)
        data.put_array("options", self._options, conversion=entity_factory.serialize_command_option)
        return data

    async def create(
        self,
        rest: rest_api.RESTClient,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        /,
        *,
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> commands.SlashCommand:
        return await rest.create_slash_command(
            application,
            self._name,
            self._description,
            guild=guild,
            default_permission=self._default_permission,
            options=self._options,
        )

Builder class for slash commands.

Variables and properties
#  default_permission: Union[bool, hikari.undefined.UndefinedType]

Whether the command should be enabled by default (without any permissions).

#  description: str

Return the description to set for this command.

Warning: This should be inclusively between 1-100 characters in length.

Returns
  • str: The description to set for this command.
#  name: str

Name to set for this command.

Warning: This should match the regex ^[\w-]{1,32}$ in Unicode mode and must be lowercase.

Sequence of up to 25 of the options set for this command.

Returns

Return the type of this command.

Returns
Methods
#  def __init__(
   self,
   name: str,
   description: str,
   *,
   id: Union[hikari.snowflakes.Snowflake, hikari.undefined.UndefinedType] = UNDEFINED,
   default_permission: Union[bool, hikari.undefined.UndefinedType] = UNDEFINED,
   options: List[hikari.commands.CommandOption] = NOTHING
):
View Source
def __init__(self, name, description, *, id=attr_dict['_id'].default, default_permission=attr_dict['_default_permission'].default, options=NOTHING):
    self._name = name
    self._id = id
    self._default_permission = default_permission
    self._description = description
    if options is not NOTHING:
        self._options = options
    else:
        self._options = __attr_factory__options()

Method generated by attrs for class SlashCommandBuilder.

#  def add_option(
   self: ~_SlashCommandBuilderT,
   option: hikari.commands.CommandOption
) -> ~_SlashCommandBuilderT:
View Source
    def add_option(self: _SlashCommandBuilderT, option: commands.CommandOption) -> _SlashCommandBuilderT:
        self._options.append(option)
        return self

Add an option to this command.

Note: A command can have up to 25 options.

Parameters
Returns
  • CommandBuilder: Object of this command builder to allow for chained calls.
View Source
    def build(self, entity_factory: entity_factory_.EntityFactory, /) -> data_binding.JSONObjectBuilder:
        data = super().build(entity_factory)
        data.put("description", self._description)
        data.put_array("options", self._options, conversion=entity_factory.serialize_command_option)
        return data

Build a JSON object from this builder.

Parameters
Returns
View Source
    async def create(
        self,
        rest: rest_api.RESTClient,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        /,
        *,
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> commands.SlashCommand:
        return await rest.create_slash_command(
            application,
            self._name,
            self._description,
            guild=guild,
            default_permission=self._default_permission,
            options=self._options,
        )

Create this command through a REST call.

Parameters
Other Parameters
Returns
#  def set_default_permission(
   self: ~_CommandBuilderT,
   state: Union[bool, hikari.undefined.UndefinedType],
   /
) -> ~_CommandBuilderT:
View Source
    def set_default_permission(self: _CommandBuilderT, state: undefined.UndefinedOr[bool], /) -> _CommandBuilderT:
        self._default_permission = state
        return self

Whether this command should be enabled by default (without any permissions).

Parameters
Returns
  • CommandBuilder: Object of this command builder to allow for chained calls.
#  def set_id(
   self: ~_CommandBuilderT,
   id_: Union[hikari.snowflakes.Snowflake, int, hikari.undefined.UndefinedType],
   /
) -> ~_CommandBuilderT:
View Source
    def set_id(self: _CommandBuilderT, id_: undefined.UndefinedOr[snowflakes.Snowflakeish], /) -> _CommandBuilderT:
        self._id = snowflakes.Snowflake(id_) if id_ is not undefined.UNDEFINED else undefined.UNDEFINED
        return self

Set the ID of this command.

Parameters
Returns
  • CommandBuilder: Object of this command builder to allow for chained calls.
#  
@typing.final
class TypingIndicator(hikari.api.special_endpoints.TypingIndicator):
View Source
@typing.final
class TypingIndicator(special_endpoints.TypingIndicator):
    """Result type of `hikari.api.rest.RESTClient.trigger_typing`.

    This is an object that can either be awaited like a coroutine to trigger
    the typing indicator once, or an async context manager to keep triggering
    the typing indicator repeatedly until the context finishes.

    .. note::
        This is a helper class that is used by `hikari.api.rest.RESTClient`.
        You should only ever need to use instances of this class that are
        produced by that API.
    """

    __slots__: typing.Sequence[str] = ("_route", "_request_call", "_task", "_rest_close_event", "_task_name")

    def __init__(
        self,
        request_call: typing.Callable[
            ..., typing.Coroutine[None, None, typing.Union[None, data_binding.JSONObject, data_binding.JSONArray]]
        ],
        channel: snowflakes.SnowflakeishOr[channels.TextableChannel],
        rest_closed_event: asyncio.Event,
    ) -> None:
        self._route = routes.POST_CHANNEL_TYPING.compile(channel=channel)
        self._request_call = request_call
        self._task_name = f"repeatedly trigger typing in {channel}"
        self._task: typing.Optional[asyncio.Task[None]] = None
        self._rest_close_event = rest_closed_event

    def __await__(self) -> typing.Generator[typing.Any, typing.Any, typing.Any]:
        return self._request_call(self._route).__await__()

    async def __aenter__(self) -> None:
        if self._task is not None:
            raise TypeError("Cannot enter a typing indicator context more than once")
        self._task = asyncio.create_task(self._keep_typing(), name=self._task_name)

    async def __aexit__(
        self,
        exc_type: typing.Optional[typing.Type[BaseException]],
        exc_val: typing.Optional[BaseException],
        exc_tb: typing.Optional[types.TracebackType],
    ) -> None:
        # This will always be true, but this keeps MyPy quiet.
        if self._task is not None:
            self._task.cancel()

    # These are only included at runtime in-order to avoid the model being typed as a synchronous context manager.
    if not typing.TYPE_CHECKING:

        def __enter__(self) -> typing.NoReturn:
            # This is async only.
            cls = type(self)
            raise TypeError(f"{cls.__module__}.{cls.__qualname__} is async-only, did you mean 'async with'?") from None

        def __exit__(
            self,
            exc_type: typing.Optional[typing.Type[Exception]],
            exc_val: typing.Optional[Exception],
            exc_tb: typing.Optional[types.TracebackType],
        ) -> None:
            return None

    async def _keep_typing(self) -> None:
        # Cancelled error will occur when the context manager is requested to
        # stop.
        try:
            # If the REST API closes while typing, just stop.
            while not self._rest_close_event.is_set():
                # Use slightly less than 10s to ensure latency does not
                # cause the typing indicator to stop showing for a split
                # second if the request is slow to execute.
                try:
                    await asyncio.gather(self, asyncio.wait_for(self._rest_close_event.wait(), timeout=9.0))
                except asyncio.TimeoutError:
                    pass

        except (asyncio.CancelledError, errors.ComponentStateConflictError):
            pass

Result type of hikari.api.rest.RESTClient.trigger_typing.

This is an object that can either be awaited like a coroutine to trigger the typing indicator once, or an async context manager to keep triggering the typing indicator repeatedly until the context finishes.

Note: This is a helper class that is used by hikari.api.rest.RESTClient. You should only ever need to use instances of this class that are produced by that API.

Methods
#  def __init__(
   self,
   request_call: Callable[..., Coroutine[NoneType, NoneType, Union[NoneType, Dict[str, Any], List[Any]]]],
   channel: Union[hikari.channels.TextableChannel, hikari.snowflakes.Snowflake, int],
   rest_closed_event: asyncio.locks.Event
):
View Source
    def __init__(
        self,
        request_call: typing.Callable[
            ..., typing.Coroutine[None, None, typing.Union[None, data_binding.JSONObject, data_binding.JSONArray]]
        ],
        channel: snowflakes.SnowflakeishOr[channels.TextableChannel],
        rest_closed_event: asyncio.Event,
    ) -> None:
        self._route = routes.POST_CHANNEL_TYPING.compile(channel=channel)
        self._request_call = request_call
        self._task_name = f"repeatedly trigger typing in {channel}"
        self._task: typing.Optional[asyncio.Task[None]] = None
        self._rest_close_event = rest_closed_event