Implementation of a V8 compatible REST API for Discord.

This also includes implementations designed towards providing RESTful functionality.

This module

Expand source code
Browse git
# -*- 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.
"""Implementation of a V8 compatible REST API for Discord.

This also includes implementations designed towards providing
RESTful functionality.
"""

from __future__ import annotations

__all__: typing.Sequence[str] = ("ClientCredentialsStrategy", "RESTApp", "RESTClientImpl")

import asyncio
import base64
import contextlib
import copy
import datetime
import http
import logging
import math
import os
import platform
import sys
import typing
import urllib.parse

import aiohttp
import attr

from hikari import _about as about
from hikari import applications
from hikari import channels as channels_
from hikari import colors
from hikari import commands
from hikari import embeds as embeds_
from hikari import emojis
from hikari import errors
from hikari import files
from hikari import guilds
from hikari import iterators
from hikari import locales
from hikari import permissions as permissions_
from hikari import scheduled_events
from hikari import snowflakes
from hikari import traits
from hikari import undefined
from hikari import urls
from hikari import users
from hikari.api import rest as rest_api
from hikari.impl import buckets as buckets_impl
from hikari.impl import config as config_impl
from hikari.impl import entity_factory as entity_factory_impl
from hikari.impl import rate_limits
from hikari.impl import special_endpoints as special_endpoints_impl
from hikari.interactions import base_interactions
from hikari.internal import data_binding
from hikari.internal import deprecation
from hikari.internal import mentions
from hikari.internal import net
from hikari.internal import routes
from hikari.internal import time
from hikari.internal import ux

if typing.TYPE_CHECKING:
    import concurrent.futures
    import types

    from hikari import audit_logs
    from hikari import invites
    from hikari import messages as messages_
    from hikari import sessions
    from hikari import stickers
    from hikari import templates
    from hikari import voices
    from hikari import webhooks
    from hikari.api import cache as cache_api
    from hikari.api import entity_factory as entity_factory_
    from hikari.api import special_endpoints

_LOGGER: typing.Final[logging.Logger] = logging.getLogger("hikari.rest")

_APPLICATION_JSON: typing.Final[str] = "application/json"
_AUTHORIZATION_HEADER: typing.Final[str] = sys.intern("Authorization")
_HTTP_USER_AGENT: typing.Final[str] = (
    f"DiscordBot ({about.__url__}, {about.__version__}) {about.__author__} "
    f"AIOHTTP/{aiohttp.__version__} "
    f"{platform.python_implementation()}/{platform.python_version()} {platform.system()} {platform.architecture()[0]}"
)
_USER_AGENT_HEADER: typing.Final[str] = sys.intern("User-Agent")
_X_AUDIT_LOG_REASON_HEADER: typing.Final[str] = sys.intern("X-Audit-Log-Reason")
_X_RATELIMIT_BUCKET_HEADER: typing.Final[str] = sys.intern("X-RateLimit-Bucket")
_X_RATELIMIT_LIMIT_HEADER: typing.Final[str] = sys.intern("X-RateLimit-Limit")
_X_RATELIMIT_REMAINING_HEADER: typing.Final[str] = sys.intern("X-RateLimit-Remaining")
_X_RATELIMIT_RESET_AFTER_HEADER: typing.Final[str] = sys.intern("X-RateLimit-Reset-After")
_RETRY_ERROR_CODES: typing.Final[typing.Set[int]] = {500, 502, 503, 504}
_MAX_BACKOFF_DURATION: typing.Final[int] = 16


class ClientCredentialsStrategy(rest_api.TokenStrategy):
    """Strategy class for handling client credential OAuth2 authorization.

    Parameters
    ----------
    client: typing.Optional[snowflakes.SnowflakeishOr[guilds.PartialApplication]]
        Object or ID of the application this client credentials strategy should
        authorize as.
    client_secret : typing.Optional[builtins.str]
        Client secret to use when authorizing.

    Other Parameters
    ----------------
    scopes : typing.Sequence[str]
        The scopes to authorize for.
    """

    __slots__: typing.Sequence[str] = (
        "_client_id",
        "_client_secret",
        "_exception",
        "_expire_at",
        "_lock",
        "_scopes",
        "_token",
    )

    def __init__(
        self,
        client: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        client_secret: str,
        *,
        scopes: typing.Sequence[typing.Union[applications.OAuth2Scope, str]] = (
            applications.OAuth2Scope.APPLICATIONS_COMMANDS_UPDATE,
            applications.OAuth2Scope.IDENTIFY,
        ),
    ) -> None:
        self._client_id = snowflakes.Snowflake(client)
        self._client_secret = client_secret
        self._exception: typing.Optional[errors.ClientHTTPResponseError] = None
        self._expire_at = 0.0
        self._lock = asyncio.Lock()
        self._scopes = tuple(scopes)
        self._token: typing.Optional[str] = None

    @property
    def client_id(self) -> snowflakes.Snowflake:
        """ID of the application this token strategy authenticates with.

        Returns
        -------
        hikari.snowflakes.Snowflake
            ID of the application this token strategy authenticates with.
        """
        return self._client_id

    @property
    def _is_expired(self) -> bool:
        return time.monotonic() >= self._expire_at

    @property
    def scopes(self) -> typing.Sequence[typing.Union[applications.OAuth2Scope, str]]:
        """Scopes this token strategy authenticates for.

        Returns
        -------
        typing.Sequence[typing.Union[hikari.applications.OAuth2Scope, builtins.str]]
            The scopes this token strategy authenticates for.
        """
        return self._scopes

    @property
    def token_type(self) -> applications.TokenType:
        return applications.TokenType.BEARER

    async def acquire(self, client: rest_api.RESTClient) -> str:
        if self._token and not self._is_expired:
            return self._token

        async with self._lock:
            if self._token and not self._is_expired:
                return self._token

            if self._exception:
                # If we don't copy the exception then python keeps adding onto the stack each time it's raised.
                raise copy.copy(self._exception) from None

            try:
                response = await client.authorize_client_credentials_token(
                    client=self._client_id, client_secret=self._client_secret, scopes=self._scopes
                )

            except errors.ClientHTTPResponseError as exc:
                if not isinstance(exc, errors.RateLimitedError):
                    # If we don't copy the exception then python keeps adding onto the stack each time it's raised.
                    self._exception = copy.copy(exc)

                raise

            # Expires in is lowered a bit in-order to lower the chance of a dead token being used.
            self._expire_at = time.monotonic() + math.floor(response.expires_in.total_seconds() * 0.99)
            self._token = f"{response.token_type} {response.access_token}"
            return self._token

    def invalidate(self, token: typing.Optional[str]) -> None:
        if not token or token == self._token:
            self._expire_at = 0.0
            self._token = None


class _RESTProvider(traits.RESTAware):
    __slots__: typing.Sequence[str] = ("_entity_factory", "_executor", "_rest")

    def __init__(
        self,
        entity_factory: typing.Callable[[], entity_factory_.EntityFactory],
        executor: typing.Optional[concurrent.futures.Executor],
        rest: typing.Callable[[], RESTClientImpl],
    ) -> None:
        self._entity_factory = entity_factory
        self._executor = executor
        self._rest = rest

    @property
    def entity_factory(self) -> entity_factory_.EntityFactory:
        return self._entity_factory()

    @property
    def executor(self) -> typing.Optional[concurrent.futures.Executor]:
        return self._executor

    @property
    def rest(self) -> rest_api.RESTClient:
        return self._rest()

    @property
    def http_settings(self) -> config_impl.HTTPSettings:
        return self._rest().http_settings

    @property
    def proxy_settings(self) -> config_impl.ProxySettings:
        return self._rest().proxy_settings


class RESTApp(traits.ExecutorAware):
    """The base for a HTTP-only Discord application.

    This comprises of a shared TCP connector connection pool, and can have
    `RESTClientImpl` instances for specific credentials acquired
    from it.

    Parameters
    ----------
    executor : typing.Optional[concurrent.futures.Executor]
        The executor to use for blocking file IO operations. If `builtins.None`
        is passed, then the default `concurrent.futures.ThreadPoolExecutor` for
        the `asyncio.AbstractEventLoop` will be used instead.
    http_settings : typing.Optional[hikari.impl.config.HTTPSettings]
        HTTP settings to use. Sane defaults are used if this is
        `builtins.None`.
    max_rate_limit : builtins.float
        Maximum number of seconds to sleep for when rate limited. If a rate
        limit occurs that is longer than this value, then a
        `hikari.errors.RateLimitedError` will be raised instead of waiting.

        This is provided since some endpoints may respond with non-sensible
        rate limits.

        Defaults to five minutes if unspecified.
    max_retries : typing.Optional[builtins.int]
        Maximum number of times a request will be retried if
        it fails with a `5xx` status. Defaults to 3 if set to `builtins.None`.
    proxy_settings : typing.Optional[hikari.impl.config.ProxySettings]
        Proxy settings to use. If `builtins.None` then no proxy configuration
        will be used.
    url : typing.Optional[builtins.str]
        The base URL for the API. You can generally leave this as being
        `builtins.None` and the correct default API base URL will be generated.

    !!! note
        This event loop will be bound to a connector when the first call
        to `acquire` is made.
    """

    __slots__: typing.Sequence[str] = (
        "_executor",
        "_http_settings",
        "_max_rate_limit",
        "_max_retries",
        "_proxy_settings",
        "_url",
    )

    def __init__(
        self,
        *,
        executor: typing.Optional[concurrent.futures.Executor] = None,
        http_settings: typing.Optional[config_impl.HTTPSettings] = None,
        max_rate_limit: float = 300,
        max_retries: int = 3,
        proxy_settings: typing.Optional[config_impl.ProxySettings] = None,
        url: typing.Optional[str] = None,
    ) -> None:
        self._http_settings = config_impl.HTTPSettings() if http_settings is None else http_settings
        self._proxy_settings = config_impl.ProxySettings() if proxy_settings is None else proxy_settings
        self._executor = executor
        self._max_rate_limit = max_rate_limit
        self._max_retries = max_retries
        self._url = url

    @property
    def executor(self) -> typing.Optional[concurrent.futures.Executor]:
        return self._executor

    @property
    def http_settings(self) -> config_impl.HTTPSettings:
        return self._http_settings

    @property
    def proxy_settings(self) -> config_impl.ProxySettings:
        return self._proxy_settings

    @typing.overload
    def acquire(self, token: typing.Optional[rest_api.TokenStrategy] = None) -> RESTClientImpl:
        ...

    @typing.overload
    def acquire(
        self,
        token: str,
        token_type: typing.Union[str, applications.TokenType] = applications.TokenType.BEARER,
    ) -> RESTClientImpl:
        ...

    def acquire(
        self,
        token: typing.Union[str, rest_api.TokenStrategy, None] = None,
        token_type: typing.Union[str, applications.TokenType, None] = None,
    ) -> RESTClientImpl:
        """Acquire an instance of this REST client.

        !!! note
            The returned REST client should be started before it can be used,
            either by calling `RESTClientImpl.start` or by using it as an
            asynchronous context manager.

        Examples
        --------
        ```py
        rest_app = RESTApp()

        # Using the returned client as a context manager to implicitly start
        # and stop it.
        async with rest_app.acquire("A token", "Bot") as client:
            user = await client.fetch_my_user()
        ```

        Parameters
        ----------
        token : typing.Union[builtins.str, builtins.None, hikari.api.rest.TokenStrategy]
            The bot or bearer token. If no token is to be used,
            this can be undefined.
        token_type : typing.Union[builtins.str, hikari.applications.TokenType, builtins.None]
            The type of token in use. This should only be passed when `builtins.str`
            is passed for `token`, can be `"Bot"` or `"Bearer"` and will be
            defaulted to `"Bearer"` in this situation.

            This should be left as `builtins.None` when either
            `hikari.api.rest.TokenStrategy` or `builtins.None` is passed for
            `token`.

        Returns
        -------
        RESTClientImpl
            An instance of the REST client.

        Raises
        ------
        builtins.ValueError
            If `token_type` is provided when a token strategy is passed for `token`.
        """
        # Since we essentially mimic a fake App instance, we need to make a circular provider.
        # We can achieve this using a lambda. This allows the entity factory to build models that
        # are also REST-aware
        provider = _RESTProvider(lambda: entity_factory, self._executor, lambda: rest_client)
        entity_factory = entity_factory_impl.EntityFactoryImpl(provider)

        if isinstance(token, str):
            token = token.strip()

            if token_type is None:
                token_type = applications.TokenType.BEARER

        rest_client = RESTClientImpl(
            cache=None,
            entity_factory=entity_factory,
            executor=self._executor,
            http_settings=self._http_settings,
            max_rate_limit=self._max_rate_limit,
            max_retries=self._max_retries,
            proxy_settings=self._proxy_settings,
            token=token,
            token_type=token_type,
            rest_url=self._url,
        )

        return rest_client


@attr.define()
class _LiveAttributes:
    """Fields which are only present within `RESTClientImpl` while it's "alive".

    !!! note
        This must be started within an active asyncio event loop.
    """

    buckets: buckets_impl.RESTBucketManager = attr.field()
    client_session: aiohttp.ClientSession = attr.field()
    closed_event: asyncio.Event = attr.field()
    # We've been told in DAPI that this is per token.
    global_rate_limit: rate_limits.ManualRateLimiter = attr.field()
    tcp_connector: aiohttp.TCPConnector = attr.field()
    is_closing: bool = attr.field(default=False, init=False)

    @classmethod
    def build(
        cls, max_rate_limit: float, http_settings: config_impl.HTTPSettings, proxy_settings: config_impl.ProxySettings
    ) -> _LiveAttributes:
        """Build a live attributes object.

        !!! warning
            This can only be called when the current thread has an active
            asyncio loop.
        """
        # This asserts that this is called within an active event loop.
        asyncio.get_running_loop()
        tcp_connector = net.create_tcp_connector(http_settings)
        _LOGGER.log(ux.TRACE, "acquired new tcp connector")
        client_session = net.create_client_session(
            connector=tcp_connector,
            # No, this is correct. We manage closing the connector ourselves in this class.
            # This works around some other lifespan issues.
            connector_owner=False,
            http_settings=http_settings,
            raise_for_status=False,
            trust_env=proxy_settings.trust_env,
        )
        _LOGGER.log(ux.TRACE, "acquired new aiohttp client session")
        return _LiveAttributes(
            buckets=buckets_impl.RESTBucketManager(max_rate_limit),
            client_session=client_session,
            closed_event=asyncio.Event(),
            global_rate_limit=rate_limits.ManualRateLimiter(),
            tcp_connector=tcp_connector,
        )

    async def close(self) -> None:
        self.is_closing = True
        self.closed_event.set()
        self.buckets.close()
        self.global_rate_limit.close()
        await self.client_session.close()
        await self.tcp_connector.close()

    def still_alive(self) -> _LiveAttributes:
        """Chained method used to Check if `close` has been called before using this object's resources."""
        if self.is_closing:
            raise errors.ComponentStateConflictError("The REST client was closed mid-request")

        return self


# The standard exceptions are all unsloted so slotting here would be a waste of time.
@attr.define(auto_exc=True, repr=False, slots=False)
class _RetryRequest(RuntimeError):
    ...


class RESTClientImpl(rest_api.RESTClient):
    """Implementation of the V8-compatible Discord HTTP API.

    This manages making HTTP/1.1 requests to the API and using the entity
    factory within the passed application instance to deserialize JSON responses
    to Pythonic data classes that are used throughout this library.

    Parameters
    ----------
    entity_factory : hikari.api.entity_factory.EntityFactory
        The entity factory to use.
    executor : typing.Optional[concurrent.futures.Executor]
        The executor to use for blocking IO. Defaults to the `asyncio` thread
        pool if set to `builtins.None`.
    max_rate_limit : builtins.float
        Maximum number of seconds to sleep for when rate limited. If a rate
        limit occurs that is longer than this value, then a
        `hikari.errors.RateLimitedError` will be raised instead of waiting.

        This is provided since some endpoints may respond with non-sensible
        rate limits.
    max_retries : typing.Optional[builtins.int]
        Maximum number of times a request will be retried if
        it fails with a `5xx` status. Defaults to 3 if set to `builtins.None`.
    token : typing.Union[builtins.str, builtins.None, hikari.api.rest.TokenStrategy]
        The bot or bearer token. If no token is to be used,
        this can be undefined.
    token_type : typing.Union[builtins.str, hikari.applications.TokenType, builtins.None]
        The type of token in use. This must be passed when a `builtins.str` is
        passed for `token` but and can be `"Bot"` or `"Bearer"`.

        This should be left as `builtins.None` when either
        `hikari.api.rest.TokenStrategy` or `builtins.None` is passed for
        `token`.
    rest_url : builtins.str
        The HTTP API base URL. This can contain format-string specifiers to
        interpolate information such as API version in use.

    Raises
    ------
    builtins.ValueError
        * If `token_type` is provided when a token strategy is passed for `token`.
        * if `token_type` is left as `builtins.None` when a string is passed for `token`.
        * If the a value more than 5 is provided for `max_retries`
    """

    __slots__: typing.Sequence[str] = (
        "_cache",
        "_entity_factory",
        "_executor",
        "_http_settings",
        "_live_attributes",
        "_max_rate_limit",
        "_max_retries",
        "_proxy_settings",
        "_rest_url",
        "_token",
        "_token_type",
    )

    def __init__(
        self,
        *,
        cache: typing.Optional[cache_api.MutableCache],
        entity_factory: entity_factory_.EntityFactory,
        executor: typing.Optional[concurrent.futures.Executor],
        http_settings: config_impl.HTTPSettings,
        max_rate_limit: float,
        max_retries: int = 3,
        proxy_settings: config_impl.ProxySettings,
        token: typing.Union[str, None, rest_api.TokenStrategy],
        token_type: typing.Union[applications.TokenType, str, None],
        rest_url: typing.Optional[str],
    ) -> None:
        if max_retries > 5:
            raise ValueError("'max_retries' must be below or equal to 5")

        self._cache = cache
        self._entity_factory = entity_factory
        self._executor = executor
        self._http_settings = http_settings
        self._live_attributes: typing.Optional[_LiveAttributes] = None
        self._max_rate_limit = max_rate_limit
        self._max_retries = max_retries
        self._proxy_settings = proxy_settings

        self._token: typing.Union[str, rest_api.TokenStrategy, None] = None
        self._token_type: typing.Optional[str] = None
        if isinstance(token, str):
            if token_type is None:
                raise ValueError("Token type required when a str is passed for `token`")

            self._token = f"{token_type.title()} {token}"
            self._token_type = applications.TokenType(token_type.title())

        elif isinstance(token, rest_api.TokenStrategy):
            if token_type is not None:
                raise ValueError("Token type should be handled by the token strategy")

            self._token = token
            self._token_type = token.token_type

        # While passing files.URL for rest_url is not officially supported, this is still
        # casted to string here to avoid confusing issues passing a URL here could lead to.
        self._rest_url = str(rest_url) if rest_url is not None else urls.REST_API_URL

    @property
    def is_alive(self) -> bool:
        return self._live_attributes is not None

    @property
    def http_settings(self) -> config_impl.HTTPSettings:
        return self._http_settings

    @property
    def proxy_settings(self) -> config_impl.ProxySettings:
        return self._proxy_settings

    @property
    def entity_factory(self) -> entity_factory_.EntityFactory:
        return self._entity_factory

    @property
    def token_type(self) -> typing.Union[str, applications.TokenType, None]:
        return self._token_type

    @typing.final
    async def close(self) -> None:
        """Close the HTTP client and any open HTTP connections."""
        live_attributes = self._get_live_attributes()
        self._live_attributes = None
        await live_attributes.close()

    @typing.final
    def start(self) -> None:
        """Start the HTTP client.

        !!! note
            This must be called within an active event loop.

        Raises
        ------
        RuntimeError
            If this is called in an environment without an active event loop.
        """
        if self._live_attributes:
            raise errors.ComponentStateConflictError("Cannot start a REST Client which is already alive")

        self._live_attributes = _LiveAttributes.build(self._max_rate_limit, self._http_settings, self._proxy_settings)

    def _get_live_attributes(self) -> _LiveAttributes:
        if self._live_attributes:
            return self._live_attributes

        raise errors.ComponentStateConflictError("Cannot use an inactive REST client")

    async def __aenter__(self) -> RESTClientImpl:
        self.start()
        return self

    async def __aexit__(
        self,
        exc_type: typing.Optional[typing.Type[BaseException]],
        exc_val: typing.Optional[BaseException],
        exc_tb: typing.Optional[types.TracebackType],
    ) -> None:
        await self.close()

    # 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[BaseException]],
            exc_val: typing.Optional[BaseException],
            exc_tb: typing.Optional[types.TracebackType],
        ) -> None:
            return None

    @typing.final
    async def _request(
        self,
        compiled_route: routes.CompiledRoute,
        *,
        query: typing.Optional[data_binding.StringMapBuilder] = None,
        form_builder: typing.Optional[data_binding.URLEncodedFormBuilder] = None,
        json: typing.Union[data_binding.JSONObjectBuilder, data_binding.JSONArray, None] = None,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        no_auth: bool = False,
        auth: typing.Optional[str] = None,
    ) -> typing.Union[None, data_binding.JSONObject, data_binding.JSONArray]:
        # Make a ratelimit-protected HTTP request to a JSON endpoint and expect some form
        # of JSON response.
        live_attributes = self._get_live_attributes()
        headers = data_binding.StringMapBuilder()
        headers.setdefault(_USER_AGENT_HEADER, _HTTP_USER_AGENT)

        re_authed = False
        token: typing.Optional[str] = None
        if auth:
            headers[_AUTHORIZATION_HEADER] = auth

        elif not no_auth:
            if isinstance(self._token, str):
                headers[_AUTHORIZATION_HEADER] = self._token

            elif self._token is not None:
                token = await self._token.acquire(self)
                headers[_AUTHORIZATION_HEADER] = token

        # As per the docs, UTF-8 characters are only supported here if it's url-encoded.
        headers.put(_X_AUDIT_LOG_REASON_HEADER, reason, conversion=urllib.parse.quote)

        url = compiled_route.create_url(self._rest_url)

        # This is initiated the first time we hit a 5xx error to save a little memory when nothing goes wrong
        backoff: typing.Optional[rate_limits.ExponentialBackOff] = None
        retry_count = 0

        stack = contextlib.AsyncExitStack()
        trace_logging_enabled = _LOGGER.isEnabledFor(ux.TRACE)
        while True:
            try:
                uuid = time.uuid()
                async with stack:
                    form = await form_builder.build(stack) if form_builder else None

                    await stack.enter_async_context(live_attributes.still_alive().buckets.acquire(compiled_route))
                    # Buckets not using authentication still have a global
                    # rate limit, but it is different from the token one.
                    if not no_auth:
                        await live_attributes.still_alive().global_rate_limit.acquire()

                    if trace_logging_enabled:
                        _LOGGER.log(
                            ux.TRACE,
                            "%s %s %s\n%s",
                            uuid,
                            compiled_route.method,
                            url,
                            self._stringify_http_message(headers, json),
                        )
                        start = time.monotonic()

                    # Make the request.
                    response = await live_attributes.still_alive().client_session.request(
                        compiled_route.method,
                        url,
                        headers=headers,
                        params=query,
                        json=json,
                        data=form,
                        allow_redirects=self._http_settings.max_redirects is not None,
                        max_redirects=self._http_settings.max_redirects,
                        proxy=self._proxy_settings.url,
                        proxy_headers=self._proxy_settings.all_headers,
                    )

                    if trace_logging_enabled:
                        time_taken = (time.monotonic() - start) * 1_000  # pyright: ignore[reportUnboundVariable]
                        _LOGGER.log(
                            ux.TRACE,
                            "%s %s %s in %sms\n%s",
                            uuid,
                            response.status,
                            response.reason,
                            time_taken,
                            self._stringify_http_message(response.headers, await response.read()),
                        )

                    # Ensure we are not rate limited, and update rate limiting headers where appropriate.
                    await self._parse_ratelimits(compiled_route, response, live_attributes)

                # Don't bother processing any further if we got NO CONTENT. There's not anything
                # to check.
                if response.status == http.HTTPStatus.NO_CONTENT:
                    return None

                # Handle the response when everything went good
                if 200 <= response.status < 300:
                    if response.content_type == _APPLICATION_JSON:
                        # Only deserializing here stops Cloudflare shenanigans messing us around.
                        return data_binding.load_json(await response.read())

                    real_url = str(response.real_url)
                    raise errors.HTTPError(f"Expected JSON [{response.content_type=}, {real_url=}]")

                # Handling 5xx errors
                if response.status in _RETRY_ERROR_CODES and retry_count < self._max_retries:
                    if backoff is None:
                        backoff = rate_limits.ExponentialBackOff(maximum=_MAX_BACKOFF_DURATION)

                    sleep_time = next(backoff)
                    _LOGGER.warning(
                        "Received status %s on request, backing off for %.2fs and retrying. Retries remaining: %s",
                        response.status,
                        sleep_time,
                        self._max_retries - retry_count,
                    )
                    retry_count += 1

                    await asyncio.sleep(sleep_time)
                    continue

                # Attempt to re-auth on UNAUTHORIZED if we are using a TokenStrategy
                can_re_auth = response.status == 401 and not (auth or no_auth or re_authed)
                if can_re_auth and isinstance(self._token, rest_api.TokenStrategy):
                    assert token is not None
                    self._token.invalidate(token)
                    token = await self._token.acquire(self)
                    headers[_AUTHORIZATION_HEADER] = token
                    re_authed = True
                    continue

                await self._handle_error_response(response)

            except _RetryRequest:
                continue

    @staticmethod
    @typing.final
    def _stringify_http_message(headers: data_binding.Headers, body: typing.Any) -> str:
        string = "\n".join(
            f"    {name}: {value}" if name != _AUTHORIZATION_HEADER else f"    {name}: **REDACTED TOKEN**"
            for name, value in headers.items()
        )

        if body is not None:
            string += "\n\n    "
            string += body.decode("ascii") if isinstance(body, bytes) else str(body)

        return string

    @staticmethod
    @typing.final
    async def _handle_error_response(response: aiohttp.ClientResponse) -> typing.NoReturn:
        raise await net.generate_error_response(response)

    @typing.final
    async def _parse_ratelimits(
        self, compiled_route: routes.CompiledRoute, response: aiohttp.ClientResponse, live_attributes: _LiveAttributes
    ) -> None:
        # Handle rate limiting.
        resp_headers = response.headers
        limit = int(resp_headers.get(_X_RATELIMIT_LIMIT_HEADER, "1"))
        remaining = int(resp_headers.get(_X_RATELIMIT_REMAINING_HEADER, "1"))
        bucket = resp_headers.get(_X_RATELIMIT_BUCKET_HEADER)
        reset_after = float(resp_headers.get(_X_RATELIMIT_RESET_AFTER_HEADER, "0"))

        if bucket:
            live_attributes.still_alive().buckets.update_rate_limits(
                compiled_route=compiled_route,
                bucket_header=bucket,
                remaining_header=remaining,
                limit_header=limit,
                reset_after=reset_after,
            )

        if response.status != http.HTTPStatus.TOO_MANY_REQUESTS:
            return

        # Discord have started applying ratelimits to operations on some endpoints
        # based on specific fields used in the JSON body.
        # This does not get reflected in the headers. The first we know is when we
        # get a 429.
        # The issue is that we may get the same response if Discord dynamically
        # adjusts the bucket ratelimits.
        #
        # We have no mechanism for handing field-based ratelimits, so if we get
        # to here, but notice remaining is greater than zero, we should just error.
        #
        # Seems Discord may raise this on some other undocumented cases, which
        # is nice of them. Apparently some dude spamming slurs in the Python
        # guild via a leaked webhook URL made people's clients exhibit this
        # behaviour.
        #
        # If we get ratelimited when running more than one bot under the same token,
        # or if the ratelimiting logic goes wrong, we will get a 429 and expect the
        # "remaining" header to be zeroed, or even negative as I don't trust that there
        # isn't some weird edge case here somewhere in Discord's implementation.
        # We can safely retry if this happens as acquiring the bucket will handle
        # this.
        if remaining <= 0:
            _LOGGER.warning(
                "rate limited on bucket %s, maybe you are running more than one bot on this token? Retrying request...",
                bucket,
            )
            raise _RetryRequest

        if response.content_type != _APPLICATION_JSON:
            # We don't know exactly what this could imply. It is likely Cloudflare interfering
            # but I'd rather we just give up than do something resulting in multiple failed
            # requests repeatedly.
            raise errors.HTTPResponseError(
                str(response.real_url),
                http.HTTPStatus.TOO_MANY_REQUESTS,
                response.headers,
                await response.read(),
                f"received rate limited response with unexpected response type {response.content_type}",
            )

        body = await response.json()
        body_retry_after = float(body["retry_after"])

        if body.get("global", False) is True:
            _LOGGER.error(
                "rate limited on the global bucket. You should consider lowering the number of requests you make or "
                "contacting Discord to raise this limit. Backing off and retrying request..."
            )
            live_attributes.still_alive().global_rate_limit.throttle(body_retry_after)
            raise _RetryRequest

        # If the values are within 20% of each other by relativistic tolerance, it is probably
        # safe to retry the request, as they are likely the same value just with some
        # measuring difference. 20% was used as a rounded figure.
        if math.isclose(body_retry_after, reset_after, rel_tol=0.20):
            _LOGGER.error("rate limited on a sub bucket on bucket %s, but it is safe to retry", bucket)
            raise _RetryRequest

        raise errors.RateLimitedError(
            url=str(response.real_url),
            route=compiled_route,
            headers=response.headers,
            raw_body=body,
            retry_after=body_retry_after,
        )

    async def fetch_channel(
        self, channel: snowflakes.SnowflakeishOr[channels_.PartialChannel]
    ) -> channels_.PartialChannel:
        route = routes.GET_CHANNEL.compile(channel=channel)
        response = await self._request(route)
        assert isinstance(response, dict)
        result = self._entity_factory.deserialize_channel(response)

        if self._cache and isinstance(result, channels_.DMChannel):
            self._cache.set_dm_channel_id(result.recipient.id, result.id)

        return result

    async def edit_channel(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
        /,
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        topic: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        video_quality_mode: undefined.UndefinedOr[typing.Union[channels_.VideoQualityMode, int]] = undefined.UNDEFINED,
        user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
        region: undefined.UndefinedNoneOr[typing.Union[voices.VoiceRegion, str]] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Sequence[channels_.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        parent_category: undefined.UndefinedOr[
            snowflakes.SnowflakeishOr[channels_.GuildCategory]
        ] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> channels_.PartialChannel:
        route = routes.PATCH_CHANNEL.compile(channel=channel)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("position", position)
        body.put("topic", topic)
        body.put("nsfw", nsfw)
        body.put("bitrate", bitrate)
        body.put("video_quality_mode", video_quality_mode)
        body.put("user_limit", user_limit)
        body.put("rate_limit_per_user", rate_limit_per_user, conversion=time.timespan_to_int)
        body.put("rtc_region", region, conversion=str)
        body.put_snowflake("parent_id", parent_category)
        body.put_array(
            "permission_overwrites",
            permission_overwrites,
            conversion=self._entity_factory.serialize_permission_overwrite,
        )

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_channel(response)

    async def follow_channel(
        self,
        news_channel: snowflakes.SnowflakeishOr[channels_.GuildNewsChannel],
        target_channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> channels_.ChannelFollow:
        route = routes.POST_CHANNEL_FOLLOWERS.compile(channel=news_channel)
        body = data_binding.JSONObjectBuilder()
        body.put_snowflake("webhook_channel_id", target_channel)

        response = await self._request(route, json=body, reason=reason)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_channel_follow(response)

    async def delete_channel(
        self, channel: snowflakes.SnowflakeishOr[channels_.PartialChannel]
    ) -> channels_.PartialChannel:
        route = routes.DELETE_CHANNEL.compile(channel=channel)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_channel(response)

    async def edit_my_voice_state(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        channel: snowflakes.SnowflakeishOr[channels_.GuildStageChannel],
        *,
        suppress: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        request_to_speak: typing.Union[undefined.UndefinedType, bool, datetime.datetime] = undefined.UNDEFINED,
    ) -> None:
        route = routes.PATCH_MY_GUILD_VOICE_STATE.compile(guild=guild)
        body = data_binding.JSONObjectBuilder()
        body.put_snowflake("channel_id", channel)
        body.put("suppress", suppress)

        if isinstance(request_to_speak, datetime.datetime):
            body.put("request_to_speak_timestamp", request_to_speak.isoformat())

        elif request_to_speak is True:
            body.put("request_to_speak_timestamp", time.utc_datetime().isoformat())

        elif request_to_speak is False:
            body.put("request_to_speak_timestamp", None)

        await self._request(route, json=body)

    async def edit_voice_state(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        channel: snowflakes.SnowflakeishOr[channels_.GuildStageChannel],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        suppress: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> None:
        route = routes.PATCH_GUILD_VOICE_STATE.compile(guild=guild, user=user)
        body = data_binding.JSONObjectBuilder()
        body.put_snowflake("channel_id", channel)
        body.put("suppress", suppress)
        await self._request(route, json=body)

    async def edit_permission_overwrite(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
        target: typing.Union[
            snowflakes.Snowflakeish, users.PartialUser, guilds.PartialRole, channels_.PermissionOverwrite
        ],
        *,
        target_type: undefined.UndefinedOr[typing.Union[channels_.PermissionOverwriteType, int]] = undefined.UNDEFINED,
        allow: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
        deny: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        if target_type is undefined.UNDEFINED:
            if isinstance(target, users.PartialUser):
                target_type = channels_.PermissionOverwriteType.MEMBER
            elif isinstance(target, guilds.Role):
                target_type = channels_.PermissionOverwriteType.ROLE
            elif isinstance(target, channels_.PermissionOverwrite):
                target_type = target.type
            else:
                raise TypeError(
                    "Cannot determine the type of the target to update. Try specifying 'target_type' manually."
                )

        target = target.id if isinstance(target, channels_.PermissionOverwrite) else target
        route = routes.PUT_CHANNEL_PERMISSIONS.compile(channel=channel, overwrite=target)
        body = data_binding.JSONObjectBuilder()
        body.put("type", target_type)
        body.put("allow", allow)
        body.put("deny", deny)
        await self._request(route, json=body, reason=reason)

    async def edit_permission_overwrites(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
        target: typing.Union[
            snowflakes.Snowflakeish, users.PartialUser, guilds.PartialRole, channels_.PermissionOverwrite
        ],
        *,
        target_type: undefined.UndefinedOr[typing.Union[channels_.PermissionOverwriteType, int]] = undefined.UNDEFINED,
        allow: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
        deny: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        """Edit permissions for a specific entity in the given guild channel.

        .. deprecated:: 2.0.0.dev110
            Use `RESTClient.edit_permission_overwrite` instead.

        Parameters
        ----------
        channel : hikari.snowflakes.SnowflakeishOr[hikari.channels.GuildChannel]
            The channel to edit a permission overwrite in. This may be the
            object, or the ID of an existing channel.
        target : typing.Union[hikari.users.PartialUser, hikari.guilds.PartialRole, hikari.channels.PermissionOverwrite, hikari.snowflakes.Snowflakeish]
            The channel overwrite to edit. This may be the object or the ID of an
            existing overwrite.

        Other Parameters
        ----------------
        target_type : hikari.undefined.UndefinedOr[typing.Union[hikari.channels.PermissionOverwriteType, int]]
            If provided, the type of the target to update. If unset, will attempt to get
            the type from `target`.
        allow : hikari.undefined.UndefinedOr[hikari.permissions.Permissions]
            If provided, the new value of all allowed permissions.
        deny : hikari.undefined.UndefinedOr[hikari.permissions.Permissions]
            If provided, the new value of all disallowed permissions.
        reason : hikari.undefined.UndefinedOr[builtins.str]
            If provided, the reason that will be recorded in the audit logs.
            Maximum of 512 characters.

        Raises
        ------
        builtins.TypeError
            If `target_type` is unset and we were unable to determine the type
            from `target`.
        hikari.errors.BadRequestError
            If any of the fields that are passed have an invalid value.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.ForbiddenError
            If you are missing the `MANAGE_PERMISSIONS` permission in the channel.
        hikari.errors.NotFoundError
            If the channel is not found or the target is not found if it is
            a role.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """  # noqa: E501 - Line too long
        deprecation.warn_deprecated(
            "edit_permission_overwrites",
            removal_version="2.0.0.dev113",
            additional_info="Use 'edit_permission_overwrite' instead",
        )
        await self.edit_permission_overwrite(
            channel, target, target_type=target_type, allow=allow, deny=deny, reason=reason
        )

    async def delete_permission_overwrite(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
        target: typing.Union[
            channels_.PermissionOverwrite, guilds.PartialRole, users.PartialUser, snowflakes.Snowflakeish
        ],
    ) -> None:
        route = routes.DELETE_CHANNEL_PERMISSIONS.compile(channel=channel, overwrite=target)
        await self._request(route)

    async def fetch_channel_invites(
        self, channel: snowflakes.SnowflakeishOr[channels_.GuildChannel]
    ) -> typing.Sequence[invites.InviteWithMetadata]:
        route = routes.GET_CHANNEL_INVITES.compile(channel=channel)
        response = await self._request(route)
        assert isinstance(response, list)
        return [self._entity_factory.deserialize_invite_with_metadata(invite_payload) for invite_payload in response]

    async def create_invite(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
        *,
        max_age: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
        max_uses: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        temporary: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        unique: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        target_type: undefined.UndefinedOr[invites.TargetType] = undefined.UNDEFINED,
        target_user: undefined.UndefinedOr[snowflakes.SnowflakeishOr[users.PartialUser]] = undefined.UNDEFINED,
        target_application: undefined.UndefinedOr[
            snowflakes.SnowflakeishOr[guilds.PartialApplication]
        ] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> invites.InviteWithMetadata:
        route = routes.POST_CHANNEL_INVITES.compile(channel=channel)
        body = data_binding.JSONObjectBuilder()
        body.put("max_age", max_age, conversion=time.timespan_to_int)
        body.put("max_uses", max_uses)
        body.put("temporary", temporary)
        body.put("unique", unique)
        body.put("target_type", target_type)
        body.put_snowflake("target_user_id", target_user)
        body.put_snowflake("target_application_id", target_application)
        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_invite_with_metadata(response)

    def trigger_typing(
        self, channel: snowflakes.SnowflakeishOr[channels_.TextableChannel]
    ) -> special_endpoints.TypingIndicator:
        return special_endpoints_impl.TypingIndicator(
            request_call=self._request, channel=channel, rest_closed_event=self._get_live_attributes().closed_event
        )

    async def fetch_pins(
        self, channel: snowflakes.SnowflakeishOr[channels_.TextableChannel]
    ) -> typing.Sequence[messages_.Message]:
        route = routes.GET_CHANNEL_PINS.compile(channel=channel)
        response = await self._request(route)
        assert isinstance(response, list)
        return [self._entity_factory.deserialize_message(message_pl) for message_pl in response]

    async def pin_message(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    ) -> None:
        route = routes.PUT_CHANNEL_PINS.compile(channel=channel, message=message)
        await self._request(route)

    async def unpin_message(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    ) -> None:
        route = routes.DELETE_CHANNEL_PIN.compile(channel=channel, message=message)
        await self._request(route)

    def fetch_messages(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        *,
        before: undefined.UndefinedOr[snowflakes.SearchableSnowflakeishOr[snowflakes.Unique]] = undefined.UNDEFINED,
        after: undefined.UndefinedOr[snowflakes.SearchableSnowflakeishOr[snowflakes.Unique]] = undefined.UNDEFINED,
        around: undefined.UndefinedOr[snowflakes.SearchableSnowflakeishOr[snowflakes.Unique]] = undefined.UNDEFINED,
    ) -> iterators.LazyIterator[messages_.Message]:
        if undefined.count(before, after, around) < 2:
            raise TypeError("Expected no kwargs, or a maximum of one of 'before', 'after', 'around'")

        timestamp: undefined.UndefinedOr[str]

        if before is not undefined.UNDEFINED:
            direction = "before"
            if isinstance(before, datetime.datetime):
                timestamp = str(snowflakes.Snowflake.from_datetime(before))
            else:
                timestamp = str(int(before))
        elif after is not undefined.UNDEFINED:
            direction = "after"
            if isinstance(after, datetime.datetime):
                timestamp = str(snowflakes.Snowflake.from_datetime(after))
            else:
                timestamp = str(int(after))
        elif around is not undefined.UNDEFINED:
            direction = "around"
            if isinstance(around, datetime.datetime):
                timestamp = str(snowflakes.Snowflake.from_datetime(around))
            else:
                timestamp = str(int(around))
        else:
            direction = "before"
            timestamp = undefined.UNDEFINED

        return special_endpoints_impl.MessageIterator(
            entity_factory=self._entity_factory,
            request_call=self._request,
            channel=channel,
            direction=direction,
            first_id=timestamp,
        )

    async def fetch_message(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    ) -> messages_.Message:
        route = routes.GET_CHANNEL_MESSAGE.compile(channel=channel, message=message)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    def _build_message_payload(  # noqa: C901- Function too complex
        self,
        /,
        *,
        content: undefined.UndefinedOr[typing.Any] = undefined.UNDEFINED,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedNoneOr[
            typing.Sequence[special_endpoints.ComponentBuilder]
        ] = undefined.UNDEFINED,
        embed: undefined.UndefinedNoneOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedNoneOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        replace_attachments: bool = False,
        flags: typing.Union[undefined.UndefinedType, int, messages_.MessageFlag] = undefined.UNDEFINED,
        tts: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        mentions_reply: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
        edit: bool = False,
    ) -> typing.Tuple[data_binding.JSONObjectBuilder, typing.Optional[data_binding.URLEncodedFormBuilder]]:
        if not undefined.any_undefined(attachment, attachments):
            raise ValueError("You may only specify one of 'attachment' or 'attachments', not both")

        if not undefined.any_undefined(component, components):
            raise ValueError("You may only specify one of 'component' or 'components', not both")

        if not undefined.any_undefined(embed, embeds):
            raise ValueError("You may only specify one of 'embed' or 'embeds', not both")

        if undefined.all_undefined(embed, embeds) and isinstance(content, embeds_.Embed):
            # Syntactic sugar, common mistake to accidentally send an embed
            # as the content, so let's detect this and fix it for the user.
            embed = content
            content = undefined.UNDEFINED

        elif undefined.all_undefined(attachment, attachments) and isinstance(
            content, (files.Resource, files.RAWISH_TYPES, os.PathLike)
        ):
            # Syntactic sugar, common mistake to accidentally send an attachment
            # as the content, so let's detect this and fix it for the user. This
            # will still then work with normal implicit embed attachments as
            # we work this out later.
            attachment = content
            content = undefined.UNDEFINED

        final_attachments: typing.List[files.Resource[files.AsyncReader]] = []
        if attachment is not undefined.UNDEFINED:
            final_attachments.append(files.ensure_resource(attachment))
        elif attachments is not undefined.UNDEFINED:
            final_attachments.extend([files.ensure_resource(a) for a in attachments])

        serialized_components: undefined.UndefinedOr[typing.List[data_binding.JSONObject]] = undefined.UNDEFINED
        if component is not undefined.UNDEFINED:
            if component is not None:
                serialized_components = [component.build()]
            else:
                serialized_components = []

        elif components is not undefined.UNDEFINED:
            if components is not None:
                serialized_components = [component.build() for component in components]
            else:
                serialized_components = []

        serialized_embeds: undefined.UndefinedOr[data_binding.JSONArray] = undefined.UNDEFINED
        if embed is not undefined.UNDEFINED:
            if embed is not None:
                embed_payload, embed_attachments = self._entity_factory.serialize_embed(embed)
                final_attachments.extend(embed_attachments)
                serialized_embeds = [embed_payload]

            else:
                serialized_embeds = []

        elif embeds is not undefined.UNDEFINED:
            serialized_embeds = []
            if embeds is not None:
                for e in embeds:
                    embed_payload, embed_attachments = self._entity_factory.serialize_embed(e)
                    final_attachments.extend(embed_attachments)
                    serialized_embeds.append(embed_payload)

        body = data_binding.JSONObjectBuilder()
        body.put("content", content, conversion=lambda v: v if v is None else str(v))
        body.put("tts", tts)
        body.put("flags", flags)
        body.put("embeds", serialized_embeds)
        body.put("components", serialized_components)

        if replace_attachments:
            body.put("attachments", None)

        if not edit or not undefined.all_undefined(mentions_everyone, mentions_reply, user_mentions, role_mentions):
            body.put(
                "allowed_mentions",
                mentions.generate_allowed_mentions(mentions_everyone, mentions_reply, user_mentions, role_mentions),
            )

        if final_attachments:
            form_builder = data_binding.URLEncodedFormBuilder(executor=self._executor)

            for i, attachment in enumerate(final_attachments):
                form_builder.add_resource(f"file{i}", attachment)
            return body, form_builder

        return body, None

    async def create_message(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        content: undefined.UndefinedOr[typing.Any] = undefined.UNDEFINED,
        *,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedOr[typing.Sequence[special_endpoints.ComponentBuilder]] = undefined.UNDEFINED,
        embed: undefined.UndefinedOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        tts: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        reply: undefined.UndefinedOr[snowflakes.SnowflakeishOr[messages_.PartialMessage]] = undefined.UNDEFINED,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        mentions_reply: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
    ) -> messages_.Message:
        route = routes.POST_CHANNEL_MESSAGES.compile(channel=channel)
        body, form_builder = self._build_message_payload(
            content=content,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            tts=tts,
            mentions_everyone=mentions_everyone,
            mentions_reply=mentions_reply,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
        )
        body.put("message_reference", reply, conversion=lambda m: {"message_id": str(int(m))})

        if form_builder is not None:
            form_builder.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
            response = await self._request(route, form_builder=form_builder)
        else:
            response = await self._request(route, json=body)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    async def crosspost_message(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.GuildNewsChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    ) -> messages_.Message:
        route = routes.POST_CHANNEL_CROSSPOST.compile(channel=channel, message=message)

        response = await self._request(route)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    async def edit_message(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
        content: undefined.UndefinedOr[typing.Any] = undefined.UNDEFINED,
        *,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedNoneOr[
            typing.Sequence[special_endpoints.ComponentBuilder]
        ] = undefined.UNDEFINED,
        embed: undefined.UndefinedNoneOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedNoneOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        replace_attachments: bool = False,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        mentions_reply: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
        flags: typing.Union[undefined.UndefinedType, int, messages_.MessageFlag] = undefined.UNDEFINED,
    ) -> messages_.Message:
        route = routes.PATCH_CHANNEL_MESSAGE.compile(channel=channel, message=message)
        body, form_builder = self._build_message_payload(
            content=content,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            replace_attachments=replace_attachments,
            flags=flags,
            mentions_everyone=mentions_everyone,
            mentions_reply=mentions_reply,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
            edit=True,
        )

        if form_builder is not None:
            form_builder.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
            response = await self._request(route, form_builder=form_builder)
        else:
            response = await self._request(route, json=body)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    async def delete_message(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    ) -> None:
        route = routes.DELETE_CHANNEL_MESSAGE.compile(channel=channel, message=message)
        await self._request(route)

    async def delete_messages(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        messages: typing.Union[
            snowflakes.SnowflakeishOr[messages_.PartialMessage],
            snowflakes.SnowflakeishIterable[messages_.PartialMessage],
        ],
        /,
        *other_messages: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    ) -> None:
        route = routes.POST_DELETE_CHANNEL_MESSAGES_BULK.compile(channel=channel)

        pending: typing.List[snowflakes.SnowflakeishOr[messages_.PartialMessage]] = []
        deleted: typing.List[snowflakes.SnowflakeishOr[messages_.PartialMessage]] = []

        if isinstance(messages, typing.Iterable):  # Syntactic sugar. Allows to use iterables
            pending.extend(messages)

        else:
            pending.append(messages)

        # This maintains the order in-order to keep a predictable deletion order.
        pending.extend(other_messages)

        while pending:
            # Discord only allows 2-100 messages in the BULK_DELETE endpoint. Because of that,
            # if the user wants 101 messages deleted, we will post 100 messages in bulk delete
            # and then the last message in a normal delete.
            # Along with this, the bucket size for v6 and v7 seems to be a bit restrictive. As of
            # 30th July 2020, this endpoint returned the following headers when being ratelimited:
            #       x-ratelimit-bucket         b05c0d8c2ab83895085006a8eae073a3
            #       x-ratelimit-limit          1
            #       x-ratelimit-remaining      0
            #       x-ratelimit-reset          1596033974.096
            #       x-ratelimit-reset-after    3.000
            # This kind of defeats the point of asynchronously gathering any of these
            # in the first place really. To save clogging up the event loop
            # (albeit at a cost of maybe a couple-dozen milliseconds per call),
            # I am just gonna invoke these sequentially instead.
            try:
                if len(pending) == 1:
                    message = pending[0]
                    try:
                        await self.delete_message(channel, message)
                    except errors.NotFoundError as exc:
                        # If the message is not found then this error should be suppressed
                        # to keep consistency with how the bulk delete endpoint functions.
                        if exc.code != 10008:  # Unknown Message
                            raise

                    deleted.append(message)

                else:
                    body = data_binding.JSONObjectBuilder()
                    chunk = pending[:100]
                    body.put_snowflake_array("messages", chunk)
                    await self._request(route, json=body)
                    deleted += chunk

                pending = pending[100:]
            except Exception as ex:
                raise errors.BulkDeleteError(deleted, pending) from ex

    @staticmethod
    def _transform_emoji_to_url_format(
        emoji: typing.Union[str, emojis.Emoji],
        emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]],
        /,
    ) -> str:
        if isinstance(emoji, emojis.Emoji):
            if emoji_id is not undefined.UNDEFINED:
                raise ValueError("emoji_id shouldn't be passed when an Emoji object is passed for emoji")

            return emoji.url_name

        if emoji_id is not undefined.UNDEFINED:
            return f"{emoji}:{snowflakes.Snowflake(emoji_id)}"

        return emoji

    async def add_reaction(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
        emoji: typing.Union[str, emojis.Emoji],
        emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = undefined.UNDEFINED,
    ) -> None:
        route = routes.PUT_MY_REACTION.compile(
            emoji=self._transform_emoji_to_url_format(emoji, emoji_id),
            channel=channel,
            message=message,
        )
        await self._request(route)

    async def delete_my_reaction(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
        emoji: typing.Union[str, emojis.Emoji],
        emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = undefined.UNDEFINED,
    ) -> None:
        route = routes.DELETE_MY_REACTION.compile(
            emoji=self._transform_emoji_to_url_format(emoji, emoji_id),
            channel=channel,
            message=message,
        )
        await self._request(route)

    async def delete_all_reactions_for_emoji(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
        emoji: typing.Union[str, emojis.Emoji],
        emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = undefined.UNDEFINED,
    ) -> None:
        route = routes.DELETE_REACTION_EMOJI.compile(
            emoji=self._transform_emoji_to_url_format(emoji, emoji_id),
            channel=channel,
            message=message,
        )
        await self._request(route)

    async def delete_reaction(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        emoji: typing.Union[str, emojis.Emoji],
        emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = undefined.UNDEFINED,
    ) -> None:
        route = routes.DELETE_REACTION_USER.compile(
            emoji=self._transform_emoji_to_url_format(emoji, emoji_id),
            channel=channel,
            message=message,
            user=user,
        )
        await self._request(route)

    async def delete_all_reactions(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    ) -> None:
        route = routes.DELETE_ALL_REACTIONS.compile(channel=channel, message=message)
        await self._request(route)

    def fetch_reactions_for_emoji(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
        emoji: typing.Union[str, emojis.Emoji],
        emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = undefined.UNDEFINED,
    ) -> iterators.LazyIterator[users.User]:
        return special_endpoints_impl.ReactorIterator(
            entity_factory=self._entity_factory,
            request_call=self._request,
            channel=channel,
            message=message,
            emoji=self._transform_emoji_to_url_format(emoji, emoji_id),
        )

    async def create_webhook(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.WebhookChannelT],
        name: str,
        *,
        avatar: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> webhooks.IncomingWebhook:
        route = routes.POST_CHANNEL_WEBHOOKS.compile(channel=channel)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)

        if avatar is not undefined.UNDEFINED:
            avatar_resource = files.ensure_resource(avatar)
            async with avatar_resource.stream(executor=self._executor) as stream:
                body.put("avatar", await stream.data_uri())

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_incoming_webhook(response)

    async def fetch_webhook(
        self,
        webhook: snowflakes.SnowflakeishOr[webhooks.PartialWebhook],
        *,
        token: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> webhooks.PartialWebhook:
        if token is undefined.UNDEFINED:
            route = routes.GET_WEBHOOK.compile(webhook=webhook)
            no_auth = False
        else:
            route = routes.GET_WEBHOOK_WITH_TOKEN.compile(webhook=webhook, token=token)
            no_auth = True

        response = await self._request(route, no_auth=no_auth)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_webhook(response)

    async def fetch_channel_webhooks(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.WebhookChannelT],
    ) -> typing.Sequence[webhooks.PartialWebhook]:
        route = routes.GET_CHANNEL_WEBHOOKS.compile(channel=channel)
        response = await self._request(route)
        assert isinstance(response, list)
        return [self._entity_factory.deserialize_webhook(webhook_pl) for webhook_pl in response]

    async def fetch_guild_webhooks(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    ) -> typing.Sequence[webhooks.PartialWebhook]:
        route = routes.GET_GUILD_WEBHOOKS.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        return [self._entity_factory.deserialize_webhook(webhook_payload) for webhook_payload in response]

    async def edit_webhook(
        self,
        webhook: snowflakes.SnowflakeishOr[webhooks.PartialWebhook],
        *,
        token: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        avatar: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
        channel: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.WebhookChannelT]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> webhooks.PartialWebhook:
        if token is undefined.UNDEFINED:
            route = routes.PATCH_WEBHOOK.compile(webhook=webhook)
            no_auth = False
        else:
            route = routes.PATCH_WEBHOOK_WITH_TOKEN.compile(webhook=webhook, token=token)
            no_auth = True

        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put_snowflake("channel", channel)

        if avatar is None:
            body.put("avatar", None)
        elif avatar is not undefined.UNDEFINED:
            avatar_resource = files.ensure_resource(avatar)
            async with avatar_resource.stream(executor=self._executor) as stream:
                body.put("avatar", await stream.data_uri())

        response = await self._request(route, json=body, reason=reason, no_auth=no_auth)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_webhook(response)

    async def delete_webhook(
        self,
        webhook: snowflakes.SnowflakeishOr[webhooks.PartialWebhook],
        *,
        token: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        if token is undefined.UNDEFINED:
            route = routes.DELETE_WEBHOOK.compile(webhook=webhook)
            no_auth = False
        else:
            route = routes.DELETE_WEBHOOK_WITH_TOKEN.compile(webhook=webhook, token=token)
            no_auth = True

        await self._request(route, no_auth=no_auth)

    async def execute_webhook(
        self,
        webhook: typing.Union[webhooks.ExecutableWebhook, snowflakes.Snowflakeish],
        token: str,
        content: undefined.UndefinedOr[typing.Any] = undefined.UNDEFINED,
        *,
        username: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        avatar_url: typing.Union[undefined.UndefinedType, str, files.URL] = undefined.UNDEFINED,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedOr[typing.Sequence[special_endpoints.ComponentBuilder]] = undefined.UNDEFINED,
        embed: undefined.UndefinedOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        tts: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
        flags: typing.Union[undefined.UndefinedType, int, messages_.MessageFlag] = undefined.UNDEFINED,
    ) -> messages_.Message:
        # int(ExecutableWebhook) isn't guaranteed to be valid nor the ID used to execute this entity as a webhook.
        webhook_id = webhook if isinstance(webhook, int) else webhook.webhook_id
        route = routes.POST_WEBHOOK_WITH_TOKEN.compile(webhook=webhook_id, token=token)

        query = data_binding.StringMapBuilder()
        query.put("wait", True)

        body, form_builder = self._build_message_payload(
            content=content,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            tts=tts,
            flags=flags,
            mentions_everyone=mentions_everyone,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
        )
        body.put("username", username)
        body.put("avatar_url", avatar_url, conversion=str)

        if form_builder is not None:
            form_builder.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
            response = await self._request(route, form_builder=form_builder, query=query, no_auth=True)
        else:
            response = await self._request(route, json=body, query=query, no_auth=True)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    async def fetch_webhook_message(
        self,
        webhook: typing.Union[webhooks.ExecutableWebhook, snowflakes.Snowflakeish],
        token: str,
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    ) -> messages_.Message:
        # int(ExecutableWebhook) isn't guaranteed to be valid nor the ID used to execute this entity as a webhook.
        webhook_id = webhook if isinstance(webhook, int) else webhook.webhook_id
        route = routes.GET_WEBHOOK_MESSAGE.compile(webhook=webhook_id, token=token, message=message)
        response = await self._request(route, no_auth=True)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    async def edit_webhook_message(
        self,
        webhook: typing.Union[webhooks.ExecutableWebhook, snowflakes.Snowflakeish],
        token: str,
        message: snowflakes.SnowflakeishOr[messages_.Message],
        content: undefined.UndefinedNoneOr[typing.Any] = undefined.UNDEFINED,
        *,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedNoneOr[
            typing.Sequence[special_endpoints.ComponentBuilder]
        ] = undefined.UNDEFINED,
        embed: undefined.UndefinedNoneOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedNoneOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        replace_attachments: bool = False,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
    ) -> messages_.Message:
        # int(ExecutableWebhook) isn't guaranteed to be valid nor the ID used to execute this entity as a webhook.
        webhook_id = webhook if isinstance(webhook, int) else webhook.webhook_id
        route = routes.PATCH_WEBHOOK_MESSAGE.compile(webhook=webhook_id, token=token, message=message)

        body, form_builder = self._build_message_payload(
            content=content,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            replace_attachments=replace_attachments,
            mentions_everyone=mentions_everyone,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
            edit=True,
        )

        if form_builder is not None:
            form_builder.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
            response = await self._request(route, form_builder=form_builder, no_auth=True)
        else:
            response = await self._request(route, json=body, no_auth=True)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    async def delete_webhook_message(
        self,
        webhook: typing.Union[webhooks.ExecutableWebhook, snowflakes.Snowflakeish],
        token: str,
        message: snowflakes.SnowflakeishOr[messages_.Message],
    ) -> None:
        # int(ExecutableWebhook) isn't guaranteed to be valid nor the ID used to execute this entity as a webhook.
        webhook_id = webhook if isinstance(webhook, int) else webhook.webhook_id
        route = routes.DELETE_WEBHOOK_MESSAGE.compile(webhook=webhook_id, token=token, message=message)
        await self._request(route, no_auth=True)

    async def fetch_gateway_url(self) -> str:
        route = routes.GET_GATEWAY.compile()
        # This doesn't need authorization.
        response = await self._request(route, no_auth=True)
        assert isinstance(response, dict)
        url = response["url"]
        assert isinstance(url, str)
        return url

    async def fetch_gateway_bot_info(self) -> sessions.GatewayBotInfo:
        route = routes.GET_GATEWAY_BOT.compile()
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_gateway_bot_info(response)

    async def fetch_invite(self, invite: typing.Union[invites.InviteCode, str]) -> invites.Invite:
        route = routes.GET_INVITE.compile(invite_code=invite if isinstance(invite, str) else invite.code)
        query = data_binding.StringMapBuilder()
        query.put("with_counts", True)
        query.put("with_expiration", True)
        response = await self._request(route, query=query)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_invite(response)

    async def delete_invite(self, invite: typing.Union[invites.InviteCode, str]) -> invites.Invite:
        route = routes.DELETE_INVITE.compile(invite_code=invite if isinstance(invite, str) else invite.code)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_invite(response)

    async def fetch_my_user(self) -> users.OwnUser:
        route = routes.GET_MY_USER.compile()
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_my_user(response)

    async def edit_my_user(
        self,
        *,
        username: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        avatar: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
    ) -> users.OwnUser:
        route = routes.PATCH_MY_USER.compile()
        body = data_binding.JSONObjectBuilder()
        body.put("username", username)

        if avatar is None:
            body.put("avatar", None)
        elif avatar is not undefined.UNDEFINED:
            avatar_resource = files.ensure_resource(avatar)
            async with avatar_resource.stream(executor=self._executor) as stream:
                body.put("avatar", await stream.data_uri())

        response = await self._request(route, json=body)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_my_user(response)

    async def fetch_my_connections(self) -> typing.Sequence[applications.OwnConnection]:
        route = routes.GET_MY_CONNECTIONS.compile()
        response = await self._request(route)
        assert isinstance(response, list)
        return [self._entity_factory.deserialize_own_connection(connection_payload) for connection_payload in response]

    def fetch_my_guilds(
        self,
        *,
        newest_first: bool = False,
        start_at: undefined.UndefinedOr[snowflakes.SearchableSnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> iterators.LazyIterator[applications.OwnGuild]:
        if start_at is undefined.UNDEFINED:
            start_at = snowflakes.Snowflake.max() if newest_first else snowflakes.Snowflake.min()
        elif isinstance(start_at, datetime.datetime):
            start_at = snowflakes.Snowflake.from_datetime(start_at)
        else:
            start_at = int(start_at)

        return special_endpoints_impl.OwnGuildIterator(
            entity_factory=self._entity_factory,
            request_call=self._request,
            newest_first=newest_first,
            first_id=str(start_at),
        )

    async def leave_guild(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild], /) -> None:
        route = routes.DELETE_MY_GUILD.compile(guild=guild)
        await self._request(route)

    async def create_dm_channel(self, user: snowflakes.SnowflakeishOr[users.PartialUser], /) -> channels_.DMChannel:
        route = routes.POST_MY_CHANNELS.compile()
        body = data_binding.JSONObjectBuilder()
        body.put_snowflake("recipient_id", user)
        response = await self._request(route, json=body)
        assert isinstance(response, dict)
        channel = self._entity_factory.deserialize_dm(response)

        if self._cache:
            self._cache.set_dm_channel_id(user, channel.id)

        return channel

    async def fetch_application(self) -> applications.Application:
        route = routes.GET_MY_APPLICATION.compile()
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_application(response)

    async def fetch_authorization(self) -> applications.AuthorizationInformation:
        route = routes.GET_MY_AUTHORIZATION.compile()
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_authorization_information(response)

    @staticmethod
    def _gen_oauth2_token(client: snowflakes.SnowflakeishOr[guilds.PartialApplication], client_secret: str) -> str:
        token = base64.b64encode(f"{int(client)}:{client_secret}".encode()).decode("utf-8")
        return f"{applications.TokenType.BASIC} {token}"

    async def authorize_client_credentials_token(
        self,
        client: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        client_secret: str,
        scopes: typing.Sequence[typing.Union[applications.OAuth2Scope, str]],
    ) -> applications.PartialOAuth2Token:
        route = routes.POST_TOKEN.compile()
        form_builder = data_binding.URLEncodedFormBuilder()
        form_builder.add_field("grant_type", "client_credentials")
        form_builder.add_field("scope", " ".join(scopes))

        response = await self._request(
            route, form_builder=form_builder, auth=self._gen_oauth2_token(client, client_secret)
        )
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_partial_token(response)

    async def authorize_access_token(
        self,
        client: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        client_secret: str,
        code: str,
        redirect_uri: str,
    ) -> applications.OAuth2AuthorizationToken:
        route = routes.POST_TOKEN.compile()
        form_builder = data_binding.URLEncodedFormBuilder()
        form_builder.add_field("grant_type", "authorization_code")
        form_builder.add_field("code", code)
        form_builder.add_field("redirect_uri", redirect_uri)

        response = await self._request(
            route, form_builder=form_builder, auth=self._gen_oauth2_token(client, client_secret)
        )
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_authorization_token(response)

    async def refresh_access_token(
        self,
        client: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        client_secret: str,
        refresh_token: str,
        *,
        scopes: undefined.UndefinedOr[
            typing.Sequence[typing.Union[applications.OAuth2Scope, str]]
        ] = undefined.UNDEFINED,
    ) -> applications.OAuth2AuthorizationToken:
        route = routes.POST_TOKEN.compile()
        form_builder = data_binding.URLEncodedFormBuilder()
        form_builder.add_field("grant_type", "refresh_token")
        form_builder.add_field("refresh_token", refresh_token)

        if scopes is not undefined.UNDEFINED:
            form_builder.add_field("scope", " ".join(scopes))

        response = await self._request(
            route, form_builder=form_builder, auth=self._gen_oauth2_token(client, client_secret)
        )
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_authorization_token(response)

    async def revoke_access_token(
        self,
        client: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        client_secret: str,
        token: typing.Union[str, applications.PartialOAuth2Token],
    ) -> None:
        route = routes.POST_TOKEN_REVOKE.compile()
        form_builder = data_binding.URLEncodedFormBuilder()
        form_builder.add_field("token", str(token))
        await self._request(route, form_builder=form_builder, auth=self._gen_oauth2_token(client, client_secret))

    async def add_user_to_guild(
        self,
        access_token: typing.Union[str, applications.PartialOAuth2Token],
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        nickname: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        nick: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
        mute: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        deaf: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> typing.Optional[guilds.Member]:
        """Add a user to a guild.

        !!! note
            This requires the `access_token` to have the
            `hikari.applications.OAuth2Scope.GUILDS_JOIN` scope enabled along
            with the authorization of a Bot which has `MANAGE_INVITES`
            permission within the target guild.

        Parameters
        ----------
        access_token : typing.Union[builtins.str, hikari.applications.PartialOAuth2Token]
            Object or string of the access token to use for this request.
        guild : hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]
            The guild to add the user to. This may be the object
            or the ID of an existing guild.
        user : hikari.snowflakes.SnowflakeishOr[hikari.users.PartialUser]
            The user to add to the guild. This may be the object
            or the ID of an existing user.

        Other Parameters
        ----------------
        nickname : hikari.undefined.UndefinedOr[builtins.str]
            If provided, the nick to add to the user when he joins the guild.

            Requires the `MANAGE_NICKNAMES` permission on the guild.
        nick : hikari.undefined.UndefinedNoneOr[builtins.str]
            Deprecated alias for `nickname`.

            .. deprecated:: 2.0.0.dev106
                Use `nickname` instead.
        roles : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishSequence[hikari.guilds.PartialRole]]
            If provided, the roles to add to the user when he joins the guild.
            This may be a collection objects or IDs of existing roles.

            Requires the `MANAGE_ROLES` permission on the guild.
        mute : hikari.undefined.UndefinedOr[builtins.bool]
            If provided, the mute state to add the user when he joins the guild.

            Requires the `MUTE_MEMBERS` permission on the guild.
        deaf : hikari.undefined.UndefinedOr[builtins.bool]
            If provided, the deaf state to add the user when he joins the guild.

            Requires the `DEAFEN_MEMBERS` permission on the guild.

        Returns
        -------
        typing.Optional[hikari.guilds.Member]
            `builtins.None` if the user was already part of the guild, else
            `hikari.guilds.Member`.

        Raises
        ------
        hikari.errors.BadRequestError
            If any of the fields that are passed have an invalid value.
        hikari.errors.ForbiddenError
            If you are not part of the guild you want to add the user to,
            if you are missing permissions to do one of the things you specified,
            if you are using an access token for another user, if the token is
            bound to another bot or if the access token doesn't have the
            `hikari.applications.OAuth2Scope.GUILDS_JOIN` scope enabled.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If you own the guild or the user is not found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        if nick is not undefined.UNDEFINED:
            deprecation.warn_deprecated(
                "nick",
                removal_version="2.0.0.dev113",
                additional_info="Use 'nickname' parameter instead",
            )
            nickname = nick

        route = routes.PUT_GUILD_MEMBER.compile(guild=guild, user=user)
        body = data_binding.JSONObjectBuilder()
        body.put("access_token", str(access_token))
        body.put("nick", nickname)
        body.put("mute", mute)
        body.put("deaf", deaf)
        body.put_snowflake_array("roles", roles)

        if (response := await self._request(route, json=body)) is not None:
            assert isinstance(response, dict)
            return self._entity_factory.deserialize_member(response, guild_id=snowflakes.Snowflake(guild))
        else:
            # User already is in the guild.
            return None

    async def fetch_voice_regions(self) -> typing.Sequence[voices.VoiceRegion]:
        route = routes.GET_VOICE_REGIONS.compile()
        response = await self._request(route)
        assert isinstance(response, list)
        return [
            self._entity_factory.deserialize_voice_region(voice_region_payload) for voice_region_payload in response
        ]

    async def fetch_user(self, user: snowflakes.SnowflakeishOr[users.PartialUser]) -> users.User:
        route = routes.GET_USER.compile(user=user)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_user(response)

    def fetch_audit_log(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        *,
        before: undefined.UndefinedOr[snowflakes.SearchableSnowflakeishOr[snowflakes.Unique]] = undefined.UNDEFINED,
        user: undefined.UndefinedOr[snowflakes.SnowflakeishOr[users.PartialUser]] = undefined.UNDEFINED,
        event_type: undefined.UndefinedOr[typing.Union[audit_logs.AuditLogEventType, int]] = undefined.UNDEFINED,
    ) -> iterators.LazyIterator[audit_logs.AuditLog]:

        timestamp: undefined.UndefinedOr[str]
        if before is undefined.UNDEFINED:
            timestamp = undefined.UNDEFINED
        elif isinstance(before, datetime.datetime):
            timestamp = str(snowflakes.Snowflake.from_datetime(before))
        else:
            timestamp = str(int(before))

        return special_endpoints_impl.AuditLogIterator(
            entity_factory=self._entity_factory,
            request_call=self._request,
            guild=guild,
            before=timestamp,
            user=user,
            action_type=event_type,
        )

    async def fetch_emoji(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        emoji: snowflakes.SnowflakeishOr[emojis.CustomEmoji],
    ) -> emojis.KnownCustomEmoji:
        route = routes.GET_GUILD_EMOJI.compile(guild=guild, emoji=emoji)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_known_custom_emoji(response, guild_id=snowflakes.Snowflake(guild))

    async def fetch_guild_emojis(
        self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]
    ) -> typing.Sequence[emojis.KnownCustomEmoji]:
        route = routes.GET_GUILD_EMOJIS.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        guild_id = snowflakes.Snowflake(guild)
        return [
            self._entity_factory.deserialize_known_custom_emoji(emoji_payload, guild_id=guild_id)
            for emoji_payload in response
        ]

    async def create_emoji(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        image: files.Resourceish,
        *,
        roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> emojis.KnownCustomEmoji:
        route = routes.POST_GUILD_EMOJIS.compile(guild=guild)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        image_resource = files.ensure_resource(image)
        async with image_resource.stream(executor=self._executor) as stream:
            body.put("image", await stream.data_uri())

        body.put_snowflake_array("roles", roles)

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_known_custom_emoji(response, guild_id=snowflakes.Snowflake(guild))

    async def edit_emoji(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        emoji: snowflakes.SnowflakeishOr[emojis.CustomEmoji],
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> emojis.KnownCustomEmoji:
        route = routes.PATCH_GUILD_EMOJI.compile(guild=guild, emoji=emoji)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put_snowflake_array("roles", roles)

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_known_custom_emoji(response, guild_id=snowflakes.Snowflake(guild))

    async def delete_emoji(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        emoji: snowflakes.SnowflakeishOr[emojis.CustomEmoji],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        route = routes.DELETE_GUILD_EMOJI.compile(guild=guild, emoji=emoji)
        await self._request(route, reason=reason)

    async def fetch_available_sticker_packs(self) -> typing.Sequence[stickers.StickerPack]:
        route = routes.GET_STICKER_PACKS.compile()
        response = await self._request(route, no_auth=True)
        assert isinstance(response, dict)
        return [
            self._entity_factory.deserialize_sticker_pack(sticker_pack_payload)
            for sticker_pack_payload in response["sticker_packs"]
        ]

    async def fetch_sticker(
        self,
        sticker: snowflakes.SnowflakeishOr[stickers.PartialSticker],
    ) -> typing.Union[stickers.StandardSticker, stickers.GuildSticker]:
        route = routes.GET_STICKER.compile(sticker=sticker)
        response = await self._request(route)
        assert isinstance(response, dict)
        return (
            self._entity_factory.deserialize_guild_sticker(response)
            if "guild_id" in response
            else self._entity_factory.deserialize_standard_sticker(response)
        )

    async def fetch_guild_stickers(
        self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]
    ) -> typing.Sequence[stickers.GuildSticker]:
        route = routes.GET_GUILD_STICKERS.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        return [
            self._entity_factory.deserialize_guild_sticker(guild_sticker_payload) for guild_sticker_payload in response
        ]

    async def fetch_guild_sticker(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        sticker: snowflakes.SnowflakeishOr[stickers.PartialSticker],
    ) -> stickers.GuildSticker:
        route = routes.GET_GUILD_STICKER.compile(guild=guild, sticker=sticker)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_sticker(response)

    async def create_sticker(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        tag: str,
        image: files.Resourceish,
        *,
        description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> stickers.GuildSticker:
        route = routes.POST_GUILD_STICKERS.compile(guild=guild)
        form = data_binding.URLEncodedFormBuilder(executor=self._executor)
        form.add_field("name", name)
        form.add_field("tags", tag)
        form.add_field("description", description or "")
        form.add_resource("file", files.ensure_resource(image))

        response = await self._request(route, form_builder=form, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_sticker(response)

    async def edit_sticker(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        sticker: snowflakes.SnowflakeishOr[stickers.PartialSticker],
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        tag: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> stickers.GuildSticker:
        route = routes.PATCH_GUILD_STICKER.compile(guild=guild, sticker=sticker)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("tags", tag)
        body.put("description", description)

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_sticker(response)

    async def delete_sticker(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        sticker: snowflakes.SnowflakeishOr[stickers.PartialSticker],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        route = routes.DELETE_GUILD_STICKER.compile(guild=guild, sticker=sticker)
        await self._request(route, reason=reason)

    def guild_builder(self, name: str, /) -> special_endpoints.GuildBuilder:
        return special_endpoints_impl.GuildBuilder(
            entity_factory=self._entity_factory, executor=self._executor, request_call=self._request, name=name
        )

    async def fetch_guild(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> guilds.RESTGuild:
        route = routes.GET_GUILD.compile(guild=guild)
        query = data_binding.StringMapBuilder()
        query.put("with_counts", True)
        response = await self._request(route, query=query)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_rest_guild(response)

    async def fetch_guild_preview(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> guilds.GuildPreview:
        route = routes.GET_GUILD_PREVIEW.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_preview(response)

    async def edit_guild(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        verification_level: undefined.UndefinedOr[guilds.GuildVerificationLevel] = undefined.UNDEFINED,
        default_message_notifications: undefined.UndefinedOr[
            guilds.GuildMessageNotificationsLevel
        ] = undefined.UNDEFINED,
        explicit_content_filter_level: undefined.UndefinedOr[
            guilds.GuildExplicitContentFilterLevel
        ] = undefined.UNDEFINED,
        afk_channel: undefined.UndefinedOr[
            snowflakes.SnowflakeishOr[channels_.GuildVoiceChannel]
        ] = undefined.UNDEFINED,
        afk_timeout: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
        icon: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
        owner: undefined.UndefinedOr[snowflakes.SnowflakeishOr[users.PartialUser]] = undefined.UNDEFINED,
        splash: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
        banner: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
        system_channel: undefined.UndefinedNoneOr[
            snowflakes.SnowflakeishOr[channels_.GuildTextChannel]
        ] = undefined.UNDEFINED,
        rules_channel: undefined.UndefinedNoneOr[
            snowflakes.SnowflakeishOr[channels_.GuildTextChannel]
        ] = undefined.UNDEFINED,
        public_updates_channel: undefined.UndefinedNoneOr[
            snowflakes.SnowflakeishOr[channels_.GuildTextChannel]
        ] = undefined.UNDEFINED,
        preferred_locale: undefined.UndefinedOr[typing.Union[str, locales.Locale]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> guilds.RESTGuild:
        route = routes.PATCH_GUILD.compile(guild=guild)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("verification_level", verification_level)
        body.put("default_message_notifications", default_message_notifications)
        body.put("explicit_content_filter", explicit_content_filter_level)
        body.put("afk_timeout", afk_timeout, conversion=time.timespan_to_int)
        body.put("preferred_locale", preferred_locale, conversion=str)
        body.put_snowflake("afk_channel_id", afk_channel)
        body.put_snowflake("owner_id", owner)
        body.put_snowflake("system_channel_id", system_channel)
        body.put_snowflake("rules_channel_id", rules_channel)
        body.put_snowflake("public_updates_channel_id", public_updates_channel)

        tasks: typing.List[asyncio.Task[str]] = []

        if icon is None:
            body.put("icon", None)
        elif icon is not undefined.UNDEFINED:
            icon_resource = files.ensure_resource(icon)
            async with icon_resource.stream(executor=self._executor) as stream:
                task = asyncio.create_task(stream.data_uri())
                task.add_done_callback(lambda future: body.put("icon", future.result()))
                tasks.append(task)

        if splash is None:
            body.put("splash", None)
        elif splash is not undefined.UNDEFINED:
            splash_resource = files.ensure_resource(splash)
            async with splash_resource.stream(executor=self._executor) as stream:
                task = asyncio.create_task(stream.data_uri())
                task.add_done_callback(lambda future: body.put("splash", future.result()))
                tasks.append(task)

        if banner is None:
            body.put("banner", None)
        elif banner is not undefined.UNDEFINED:
            banner_resource = files.ensure_resource(banner)
            async with banner_resource.stream(executor=self._executor) as stream:
                task = asyncio.create_task(stream.data_uri())
                task.add_done_callback(lambda future: body.put("banner", future.result()))
                tasks.append(task)

        await asyncio.gather(*tasks)

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_rest_guild(response)

    async def delete_guild(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> None:
        route = routes.DELETE_GUILD.compile(guild=guild)
        await self._request(route)

    async def fetch_guild_channels(
        self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]
    ) -> typing.Sequence[channels_.GuildChannel]:
        route = routes.GET_GUILD_CHANNELS.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        channel_sequence = [self._entity_factory.deserialize_channel(channel_payload) for channel_payload in response]
        # Will always be guild channels unless Discord messes up severely on something!
        return typing.cast("typing.Sequence[channels_.GuildChannel]", channel_sequence)

    async def create_guild_text_channel(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        *,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        topic: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Sequence[channels_.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> channels_.GuildTextChannel:
        response = await self._create_guild_channel(
            guild,
            name,
            channels_.ChannelType.GUILD_TEXT,
            position=position,
            topic=topic,
            nsfw=nsfw,
            rate_limit_per_user=rate_limit_per_user,
            permission_overwrites=permission_overwrites,
            category=category,
            reason=reason,
        )
        return self._entity_factory.deserialize_guild_text_channel(response)

    async def create_guild_news_channel(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        *,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        topic: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Sequence[channels_.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> channels_.GuildNewsChannel:
        response = await self._create_guild_channel(
            guild,
            name,
            channels_.ChannelType.GUILD_NEWS,
            position=position,
            topic=topic,
            nsfw=nsfw,
            rate_limit_per_user=rate_limit_per_user,
            permission_overwrites=permission_overwrites,
            category=category,
            reason=reason,
        )
        return self._entity_factory.deserialize_guild_news_channel(response)

    async def create_guild_voice_channel(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        *,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        video_quality_mode: undefined.UndefinedOr[typing.Union[channels_.VideoQualityMode, int]] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Sequence[channels_.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        region: undefined.UndefinedOr[typing.Union[voices.VoiceRegion, str]] = undefined.UNDEFINED,
        category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> channels_.GuildVoiceChannel:
        response = await self._create_guild_channel(
            guild,
            name,
            channels_.ChannelType.GUILD_VOICE,
            position=position,
            user_limit=user_limit,
            bitrate=bitrate,
            video_quality_mode=video_quality_mode,
            permission_overwrites=permission_overwrites,
            region=region,
            category=category,
            reason=reason,
        )
        return self._entity_factory.deserialize_guild_voice_channel(response)

    async def create_guild_stage_channel(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        *,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Sequence[channels_.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        region: undefined.UndefinedOr[typing.Union[voices.VoiceRegion, str]] = undefined.UNDEFINED,
        category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> channels_.GuildStageChannel:
        response = await self._create_guild_channel(
            guild,
            name,
            channels_.ChannelType.GUILD_STAGE,
            position=position,
            user_limit=user_limit,
            bitrate=bitrate,
            permission_overwrites=permission_overwrites,
            region=region,
            category=category,
            reason=reason,
        )
        return self._entity_factory.deserialize_guild_stage_channel(response)

    async def create_guild_category(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        *,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Sequence[channels_.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> channels_.GuildCategory:
        response = await self._create_guild_channel(
            guild,
            name,
            channels_.ChannelType.GUILD_CATEGORY,
            position=position,
            permission_overwrites=permission_overwrites,
            reason=reason,
        )
        return self._entity_factory.deserialize_guild_category(response)

    async def _create_guild_channel(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        type_: channels_.ChannelType,
        *,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        topic: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        video_quality_mode: undefined.UndefinedOr[typing.Union[channels_.VideoQualityMode, int]] = undefined.UNDEFINED,
        user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Sequence[channels_.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        region: undefined.UndefinedOr[typing.Union[voices.VoiceRegion, str]] = undefined.UNDEFINED,
        category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> data_binding.JSONObject:
        route = routes.POST_GUILD_CHANNELS.compile(guild=guild)
        body = data_binding.JSONObjectBuilder()
        body.put("type", type_)
        body.put("name", name)
        body.put("position", position)
        body.put("topic", topic)
        body.put("nsfw", nsfw)
        body.put("bitrate", bitrate)
        body.put("video_quality_mode", video_quality_mode)
        body.put("user_limit", user_limit)
        body.put("rate_limit_per_user", rate_limit_per_user, conversion=time.timespan_to_int)
        body.put("rtc_region", region, conversion=str)
        body.put_snowflake("parent_id", category)
        body.put_array(
            "permission_overwrites",
            permission_overwrites,
            conversion=self._entity_factory.serialize_permission_overwrite,
        )

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return response

    async def reposition_channels(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        positions: typing.Mapping[int, snowflakes.SnowflakeishOr[channels_.GuildChannel]],
    ) -> None:
        route = routes.PATCH_GUILD_CHANNELS.compile(guild=guild)
        body = [{"id": str(int(channel)), "position": pos} for pos, channel in positions.items()]
        await self._request(route, json=body)

    async def fetch_member(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
    ) -> guilds.Member:
        route = routes.GET_GUILD_MEMBER.compile(guild=guild, user=user)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_member(response, guild_id=snowflakes.Snowflake(guild))

    def fetch_members(
        self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]
    ) -> iterators.LazyIterator[guilds.Member]:
        return special_endpoints_impl.MemberIterator(
            entity_factory=self._entity_factory, request_call=self._request, guild=guild
        )

    async def fetch_my_member(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> guilds.Member:
        route = routes.GET_MY_GUILD_MEMBER.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_member(response, guild_id=snowflakes.Snowflake(guild))

    async def search_members(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
    ) -> typing.Sequence[guilds.Member]:
        route = routes.GET_GUILD_MEMBERS_SEARCH.compile(guild=guild)
        query = data_binding.StringMapBuilder()
        query.put("query", name)
        query.put("limit", 1000)
        response = await self._request(route, query=query)
        assert isinstance(response, list)
        guild_id = snowflakes.Snowflake(guild)
        return [
            self._entity_factory.deserialize_member(member_payload, guild_id=guild_id) for member_payload in response
        ]

    async def edit_member(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        nickname: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
        nick: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
        roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
        mute: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        deaf: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        voice_channel: undefined.UndefinedNoneOr[
            snowflakes.SnowflakeishOr[channels_.GuildVoiceChannel]
        ] = undefined.UNDEFINED,
        communication_disabled_until: undefined.UndefinedNoneOr[datetime.datetime] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> guilds.Member:
        """Edit a guild member.

        Parameters
        ----------
        guild : hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]
            The guild to edit. This may be the object
            or the ID of an existing guild.
        user : hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]
            The guild to edit. This may be the object
            or the ID of an existing guild.

        Other Parameters
        ----------------
        nickname : hikari.undefined.UndefinedNoneOr[builtins.str]
            If provided, the new nick for the member. If `builtins.None`,
            will remove the members nick.

            Requires the `MANAGE_NICKNAMES` permission.
        nick : hikari.undefined.UndefinedNoneOr[builtins.str]
            Deprecated alias for `nickname`.

            .. deprecated:: 2.0.0.dev104
                Use `nickname` instead.
        roles : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishSequence[hikari.guilds.PartialRole]]
            If provided, the new roles for the member.

            Requires the `MANAGE_ROLES` permission.
        mute : hikari.undefined.UndefinedOr[builtins.bool]
            If provided, the new server mute state for the member.

            Requires the `MUTE_MEMBERS` permission.
        deaf : hikari.undefined.UndefinedOr[builtins.bool]
            If provided, the new server deaf state for the member.

            Requires the `DEAFEN_MEMBERS` permission.
        voice_channel : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishOr[hikari.channels.GuildVoiceChannel]]]
            If provided, `builtins.None` or the object or the ID of
            an existing voice channel to move the member to.
            If `builtins.None`, will disconnect the member from voice.

            Requires the `MOVE_MEMBERS` permission and the `CONNECT`
            permission in the original voice channel and the target
            voice channel.

            !!! note
                If the member is not in a voice channel, this will
                take no effect.
        communication_disabled_until : hikari.undefined.UndefinedNoneOr[datetime.datetime]
            If provided, the datetime when the timeout (disable communication)
            of the member expires, up to 28 days in the future, or `builtins.None`
            to remove the timeout from the member.

            Requires the `MODERATE_MEMBERS` permission.
        reason : hikari.undefined.UndefinedOr[builtins.str]
            If provided, the reason that will be recorded in the audit logs.
            Maximum of 512 characters.

        Returns
        -------
        hikari.guilds.Member
            Object of the member that was updated.

        Raises
        ------
        hikari.errors.BadRequestError
            If any of the fields that are passed have an invalid value.
        hikari.errors.ForbiddenError
            If you are missing a permission to do an action.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If the guild or the user are not found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        if nick is not undefined.UNDEFINED:
            deprecation.warn_deprecated(
                "nick",
                removal_version="2.0.0.dev113",
                additional_info="Use 'nickname' parameter instead",
            )
            nickname = nick

        route = routes.PATCH_GUILD_MEMBER.compile(guild=guild, user=user)
        body = data_binding.JSONObjectBuilder()
        body.put("nick", nickname)
        body.put("mute", mute)
        body.put("deaf", deaf)
        body.put_snowflake_array("roles", roles)

        if voice_channel is None:
            body.put("channel_id", None)
        else:
            body.put_snowflake("channel_id", voice_channel)

        if isinstance(communication_disabled_until, datetime.datetime):
            body.put("communication_disabled_until", communication_disabled_until.isoformat())
        else:
            body.put("communication_disabled_until", communication_disabled_until)

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_member(response, guild_id=snowflakes.Snowflake(guild))

    async def edit_my_member(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        *,
        nickname: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> guilds.Member:
        route = routes.PATCH_MY_GUILD_MEMBER.compile(guild=guild)
        body = data_binding.JSONObjectBuilder()
        body.put("nick", nickname)

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_member(response, guild_id=snowflakes.Snowflake(guild))

    async def edit_my_nick(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.Guild],
        nick: typing.Optional[str],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        """Edit the associated token's member nick.

        .. deprecated:: 2.0.0.dev104
            Use `RESTClient.edit_my_member`'s `nick` argument instead.

        Parameters
        ----------
        guild : hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]
            The guild to edit. This may be the object
            or the ID of an existing guild.
        nick : typing.Optional[builtins.str]
            The new nick. If `builtins.None`,
            will remove the nick.

        Other Parameters
        ----------------
        reason : hikari.undefined.UndefinedOr[builtins.str]
            If provided, the reason that will be recorded in the audit logs.
            Maximum of 512 characters.

        Raises
        ------
        hikari.errors.ForbiddenError
            If you are missing the `CHANGE_NICKNAME` permission.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If the guild is not found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        deprecation.warn_deprecated(
            "edit_permission_overwrites",
            removal_version="2.0.0.dev113",
            additional_info="Use 'edit_my_member' with the nickname parameter instead.",
        )
        await self.edit_my_member(guild, nickname=nick, reason=reason)

    async def add_role_to_member(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        role: snowflakes.SnowflakeishOr[guilds.PartialRole],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        route = routes.PUT_GUILD_MEMBER_ROLE.compile(guild=guild, user=user, role=role)
        await self._request(route, reason=reason)

    async def remove_role_from_member(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        role: snowflakes.SnowflakeishOr[guilds.PartialRole],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        route = routes.DELETE_GUILD_MEMBER_ROLE.compile(guild=guild, user=user, role=role)
        await self._request(route, reason=reason)

    async def kick_user(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        route = routes.DELETE_GUILD_MEMBER.compile(guild=guild, user=user)
        await self._request(route, reason=reason)

    def kick_member(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> typing.Coroutine[typing.Any, typing.Any, None]:
        return self.kick_user(guild, user, reason=reason)

    async def ban_user(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        delete_message_days: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        body = data_binding.JSONObjectBuilder()
        body.put("delete_message_days", delete_message_days)
        route = routes.PUT_GUILD_BAN.compile(guild=guild, user=user)
        await self._request(route, json=body, reason=reason)

    def ban_member(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        delete_message_days: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> typing.Coroutine[typing.Any, typing.Any, None]:
        return self.ban_user(guild, user, delete_message_days=delete_message_days, reason=reason)

    async def unban_user(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        route = routes.DELETE_GUILD_BAN.compile(guild=guild, user=user)
        await self._request(route, reason=reason)

    def unban_member(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> typing.Coroutine[typing.Any, typing.Any, None]:
        return self.unban_user(guild, user, reason=reason)

    async def fetch_ban(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
    ) -> guilds.GuildBan:
        route = routes.GET_GUILD_BAN.compile(guild=guild, user=user)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_member_ban(response)

    def fetch_bans(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        /,
        *,
        newest_first: bool = False,
        start_at: undefined.UndefinedOr[snowflakes.SearchableSnowflakeishOr[users.PartialUser]] = undefined.UNDEFINED,
    ) -> iterators.LazyIterator[guilds.GuildBan]:
        if start_at is undefined.UNDEFINED:
            start_at = snowflakes.Snowflake.max() if newest_first else snowflakes.Snowflake.min()
        elif isinstance(start_at, datetime.datetime):
            start_at = snowflakes.Snowflake.from_datetime(start_at)
        else:
            start_at = int(start_at)

        return special_endpoints_impl.GuildBanIterator(
            self._entity_factory, self._request, guild, newest_first, str(start_at)
        )

    async def fetch_roles(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    ) -> typing.Sequence[guilds.Role]:
        route = routes.GET_GUILD_ROLES.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        guild_id = snowflakes.Snowflake(guild)
        return [self._entity_factory.deserialize_role(role_payload, guild_id=guild_id) for role_payload in response]

    async def create_role(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        permissions: undefined.UndefinedOr[permissions_.Permissions] = permissions_.Permissions.NONE,
        color: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
        colour: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
        hoist: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        icon: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        unicode_emoji: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        mentionable: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> guilds.Role:
        if not undefined.any_undefined(color, colour):
            raise TypeError("Can not specify 'color' and 'colour' together.")

        if not undefined.any_undefined(icon, unicode_emoji):
            raise TypeError("Can not specify 'icon' and 'unicode_emoji' together.")

        route = routes.POST_GUILD_ROLES.compile(guild=guild)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("permissions", permissions)
        body.put("color", color, conversion=colors.Color.of)
        body.put("color", colour, conversion=colors.Color.of)
        body.put("hoist", hoist)
        body.put("unicode_emoji", unicode_emoji)
        body.put("mentionable", mentionable)

        if icon is not undefined.UNDEFINED:
            icon_resource = files.ensure_resource(icon)
            async with icon_resource.stream(executor=self._executor) as stream:
                body.put("icon", await stream.data_uri())

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_role(response, guild_id=snowflakes.Snowflake(guild))

    async def reposition_roles(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        positions: typing.Mapping[int, snowflakes.SnowflakeishOr[guilds.PartialRole]],
    ) -> None:
        route = routes.PATCH_GUILD_ROLES.compile(guild=guild)
        body = [{"id": str(int(role)), "position": pos} for pos, role in positions.items()]
        await self._request(route, json=body)

    async def edit_role(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        role: snowflakes.SnowflakeishOr[guilds.PartialRole],
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        permissions: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
        color: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
        colour: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
        hoist: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        icon: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
        unicode_emoji: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
        mentionable: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> guilds.Role:
        if not undefined.any_undefined(color, colour):
            raise TypeError("Can not specify 'color' and 'colour' together.")

        if not undefined.any_undefined(icon, unicode_emoji):
            raise TypeError("Can not specify 'icon' and 'unicode_emoji' together.")

        route = routes.PATCH_GUILD_ROLE.compile(guild=guild, role=role)

        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("permissions", permissions)
        body.put("color", color, conversion=colors.Color.of)
        body.put("color", colour, conversion=colors.Color.of)
        body.put("hoist", hoist)
        body.put("unicode_emoji", unicode_emoji)
        body.put("mentionable", mentionable)

        if icon is None:
            body.put("icon", None)
        elif icon is not undefined.UNDEFINED:
            icon_resource = files.ensure_resource(icon)
            async with icon_resource.stream(executor=self._executor) as stream:
                body.put("icon", await stream.data_uri())

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_role(response, guild_id=snowflakes.Snowflake(guild))

    async def delete_role(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        role: snowflakes.SnowflakeishOr[guilds.PartialRole],
    ) -> None:
        route = routes.DELETE_GUILD_ROLE.compile(guild=guild, role=role)
        await self._request(route)

    async def estimate_guild_prune_count(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        *,
        days: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        include_roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
    ) -> int:
        route = routes.GET_GUILD_PRUNE.compile(guild=guild)
        query = data_binding.StringMapBuilder()
        query.put("days", days)
        if include_roles is not undefined.UNDEFINED:
            roles = ",".join(str(int(role)) for role in include_roles)
            query.put("include_roles", roles)
        response = await self._request(route, query=query)
        assert isinstance(response, dict)
        return int(response["pruned"])

    async def begin_guild_prune(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        *,
        days: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        compute_prune_count: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        include_roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> typing.Optional[int]:
        route = routes.POST_GUILD_PRUNE.compile(guild=guild)
        body = data_binding.JSONObjectBuilder()
        body.put("days", days)
        body.put("compute_prune_count", compute_prune_count)
        body.put_snowflake_array("include_roles", include_roles)
        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        pruned = response.get("pruned")
        return int(pruned) if pruned is not None else None

    async def fetch_guild_voice_regions(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    ) -> typing.Sequence[voices.VoiceRegion]:
        route = routes.GET_GUILD_VOICE_REGIONS.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        return [
            self._entity_factory.deserialize_voice_region(voice_region_payload) for voice_region_payload in response
        ]

    async def fetch_guild_invites(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    ) -> typing.Sequence[invites.InviteWithMetadata]:
        route = routes.GET_GUILD_INVITES.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        return [self._entity_factory.deserialize_invite_with_metadata(invite_payload) for invite_payload in response]

    async def fetch_integrations(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    ) -> typing.Sequence[guilds.Integration]:
        route = routes.GET_GUILD_INTEGRATIONS.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        guild_id = snowflakes.Snowflake(guild)
        return [
            self._entity_factory.deserialize_integration(integration_payload, guild_id=guild_id)
            for integration_payload in response
        ]

    async def fetch_widget(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> guilds.GuildWidget:
        route = routes.GET_GUILD_WIDGET.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_widget(response)

    async def edit_widget(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        *,
        channel: undefined.UndefinedNoneOr[snowflakes.SnowflakeishOr[channels_.GuildChannel]] = undefined.UNDEFINED,
        enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> guilds.GuildWidget:
        route = routes.PATCH_GUILD_WIDGET.compile(guild=guild)

        body = data_binding.JSONObjectBuilder()
        body.put("enabled", enabled)
        if channel is None:
            body.put("channel", None)
        elif channel is not undefined.UNDEFINED:
            body.put_snowflake("channel", channel)

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_widget(response)

    async def fetch_welcome_screen(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> guilds.WelcomeScreen:
        route = routes.GET_GUILD_WELCOME_SCREEN.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_welcome_screen(response)

    async def edit_welcome_screen(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        *,
        description: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
        enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        channels: undefined.UndefinedNoneOr[typing.Sequence[guilds.WelcomeChannel]] = undefined.UNDEFINED,
    ) -> guilds.WelcomeScreen:
        route = routes.PATCH_GUILD_WELCOME_SCREEN.compile(guild=guild)

        body = data_binding.JSONObjectBuilder()

        body.put("description", description)
        body.put("enabled", enabled)

        if channels is not None:
            body.put_array("welcome_channels", channels, conversion=self._entity_factory.serialize_welcome_channel)

        else:
            body.put("welcome_channels", None)

        response = await self._request(route, json=body)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_welcome_screen(response)

    async def fetch_vanity_url(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> invites.VanityURL:
        route = routes.GET_GUILD_VANITY_URL.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_vanity_url(response)

    async def fetch_template(self, template: typing.Union[templates.Template, str]) -> templates.Template:
        template = template if isinstance(template, str) else template.code
        route = routes.GET_TEMPLATE.compile(template=template)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_template(response)

    async def fetch_guild_templates(
        self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]
    ) -> typing.Sequence[templates.Template]:
        route = routes.GET_GUILD_TEMPLATES.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        return [self._entity_factory.deserialize_template(template_payload) for template_payload in response]

    async def sync_guild_template(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        template: typing.Union[templates.Template, str],
    ) -> templates.Template:
        template = template if isinstance(template, str) else template.code
        route = routes.PUT_GUILD_TEMPLATE.compile(guild=guild, template=template)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_template(response)

    async def create_guild_from_template(
        self,
        template: typing.Union[str, templates.Template],
        name: str,
        *,
        icon: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
    ) -> guilds.RESTGuild:
        template = template if isinstance(template, str) else template.code
        route = routes.POST_TEMPLATE.compile(template=template)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)

        if icon is not undefined.UNDEFINED:
            icon_resource = files.ensure_resource(icon)
            async with icon_resource.stream(executor=self._executor) as stream:
                body.put("icon", await stream.data_uri())

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

    async def create_template(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        *,
        description: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
    ) -> templates.Template:
        route = routes.POST_GUILD_TEMPLATES.compile(guild=guild)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("description", description)
        response = await self._request(route, json=body)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_template(response)

    async def edit_template(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        template: typing.Union[str, templates.Template],
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        description: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
    ) -> templates.Template:
        template = template if isinstance(template, str) else template.code
        route = routes.PATCH_GUILD_TEMPLATE.compile(guild=guild, template=template)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("description", description)

        response = await self._request(route, json=body)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_template(response)

    async def delete_template(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        template: typing.Union[str, templates.Template],
    ) -> templates.Template:
        template = template if isinstance(template, str) else template.code
        route = routes.DELETE_GUILD_TEMPLATE.compile(guild=guild, template=template)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_template(response)

    def command_builder(self, name: str, description: str) -> special_endpoints.SlashCommandBuilder:
        r"""Create a slash command builder to use in `RESTClient.set_application_commands`.

        .. deprecated:: 2.0.0.dev106
            Use `RESTClient.slash_command_builder` instead.

        Parameters
        ----------
        name : builtins.str
            The command's name. This should match the regex `^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$` in
            Unicode mode and be lowercase.
        description : builtins.str
            The description to set for the command.
            This should be inclusively between 1-100 characters in length.

        Returns
        -------
        hikari.api.special_endpoints.SlashCommandBuilder
            The created command builder object.
        """
        deprecation.warn_deprecated(
            "command_builder",
            removal_version="2.0.0.dev113",
            additional_info="Use 'slash_command_builder' instead.",
        )
        return self.slash_command_builder(name, description)

    def slash_command_builder(self, name: str, description: str) -> special_endpoints.SlashCommandBuilder:
        return special_endpoints_impl.SlashCommandBuilder(name, description)

    def context_menu_command_builder(
        self,
        type: typing.Union[commands.CommandType, int],
        name: str,
    ) -> special_endpoints.ContextMenuCommandBuilder:
        return special_endpoints_impl.ContextMenuCommandBuilder(commands.CommandType(type), name)

    async def fetch_application_command(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        command: snowflakes.SnowflakeishOr[commands.PartialCommand],
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> commands.PartialCommand:
        if guild is undefined.UNDEFINED:
            route = routes.GET_APPLICATION_COMMAND.compile(application=application, command=command)

        else:
            route = routes.GET_APPLICATION_GUILD_COMMAND.compile(application=application, guild=guild, command=command)

        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_command(
            response, guild_id=snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
        )

    async def fetch_application_commands(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> typing.Sequence[commands.PartialCommand]:
        if guild is undefined.UNDEFINED:
            route = routes.GET_APPLICATION_COMMANDS.compile(application=application)

        else:
            route = routes.GET_APPLICATION_GUILD_COMMANDS.compile(application=application, guild=guild)

        query = data_binding.StringMapBuilder()
        query.put("with_localizations", True)

        response = await self._request(route, query=query)
        assert isinstance(response, list)
        guild_id = snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
        return [self._entity_factory.deserialize_command(command, guild_id=guild_id) for command in response]

    async def _create_application_command(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        type: typing.Union[commands.CommandType, int],
        name: str,
        description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        *,
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
        options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
        name_localizations: undefined.UndefinedOr[
            typing.Mapping[typing.Union[locales.Locale, str], str]
        ] = undefined.UNDEFINED,
        description_localizations: undefined.UndefinedOr[
            typing.Mapping[typing.Union[locales.Locale, str], str]
        ] = undefined.UNDEFINED,
        default_member_permissions: typing.Union[
            undefined.UndefinedType, int, permissions_.Permissions
        ] = undefined.UNDEFINED,
        dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> data_binding.JSONObject:
        if guild is undefined.UNDEFINED:
            route = routes.POST_APPLICATION_COMMAND.compile(application=application)

        else:
            route = routes.POST_APPLICATION_GUILD_COMMAND.compile(application=application, guild=guild)

        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("description", description)
        body.put("type", type)
        body.put_array("options", options, conversion=self._entity_factory.serialize_command_option)
        body.put("name_localizations", name_localizations)
        body.put("description_localizations", description_localizations)

        # Discord has some funky behaviour around what 0 means. They consider it to be the same as ADMINISTRATOR,
        # but we consider it to be the same as None for developer sanity reasons
        body.put("default_member_permissions", None if default_member_permissions == 0 else default_member_permissions)
        body.put("dm_permission", dm_enabled)

        response = await self._request(route, json=body)
        assert isinstance(response, dict)
        return response

    async def create_slash_command(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        name: str,
        description: str,
        *,
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
        options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
        name_localizations: undefined.UndefinedOr[
            typing.Mapping[typing.Union[locales.Locale, str], str]
        ] = undefined.UNDEFINED,
        description_localizations: undefined.UndefinedOr[
            typing.Mapping[typing.Union[locales.Locale, str], str]
        ] = undefined.UNDEFINED,
        default_member_permissions: typing.Union[
            undefined.UndefinedType, int, permissions_.Permissions
        ] = undefined.UNDEFINED,
        dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> commands.SlashCommand:
        response = await self._create_application_command(
            application=application,
            type=commands.CommandType.SLASH,
            name=name,
            description=description,
            guild=guild,
            options=options,
            name_localizations=name_localizations,
            description_localizations=description_localizations,
            default_member_permissions=default_member_permissions,
            dm_enabled=dm_enabled,
        )
        return self._entity_factory.deserialize_slash_command(
            response, guild_id=snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
        )

    async def create_context_menu_command(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        type: typing.Union[commands.CommandType, int],
        name: str,
        *,
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
        name_localizations: undefined.UndefinedOr[
            typing.Mapping[typing.Union[locales.Locale, str], str]
        ] = undefined.UNDEFINED,
        default_member_permissions: typing.Union[
            undefined.UndefinedType, int, permissions_.Permissions
        ] = undefined.UNDEFINED,
        dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> commands.ContextMenuCommand:
        response = await self._create_application_command(
            application=application,
            type=type,
            name=name,
            guild=guild,
            name_localizations=name_localizations,
            default_member_permissions=default_member_permissions,
            dm_enabled=dm_enabled,
        )
        return self._entity_factory.deserialize_context_menu_command(
            response, guild_id=snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
        )

    async def set_application_commands(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        commands: typing.Sequence[special_endpoints.CommandBuilder],
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> typing.Sequence[commands.PartialCommand]:
        if guild is undefined.UNDEFINED:
            route = routes.PUT_APPLICATION_COMMANDS.compile(application=application)

        else:
            route = routes.PUT_APPLICATION_GUILD_COMMANDS.compile(application=application, guild=guild)

        response = await self._request(route, json=[command.build(self._entity_factory) for command in commands])
        assert isinstance(response, list)
        guild_id = snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
        return [self._entity_factory.deserialize_command(payload, guild_id=guild_id) for payload in response]

    async def edit_application_command(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        command: snowflakes.SnowflakeishOr[commands.PartialCommand],
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
        default_member_permissions: typing.Union[
            undefined.UndefinedType, int, permissions_.Permissions
        ] = undefined.UNDEFINED,
        dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> commands.PartialCommand:
        if guild is undefined.UNDEFINED:
            route = routes.PATCH_APPLICATION_COMMAND.compile(application=application, command=command)

        else:
            route = routes.PATCH_APPLICATION_GUILD_COMMAND.compile(
                application=application, command=command, guild=guild
            )

        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("description", description)
        body.put_array("options", options, conversion=self._entity_factory.serialize_command_option)
        # Discord has some funky behaviour around what 0 means. They consider it to be the same as ADMINISTRATOR,
        # but we consider it to be the same as None for developer sanity reasons
        body.put("default_member_permissions", None if default_member_permissions == 0 else default_member_permissions)
        body.put("dm_permission", dm_enabled)

        response = await self._request(route, json=body)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_command(
            response, guild_id=snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
        )

    async def delete_application_command(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        command: snowflakes.SnowflakeishOr[commands.PartialCommand],
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> None:
        if guild is undefined.UNDEFINED:
            route = routes.DELETE_APPLICATION_COMMAND.compile(application=application, command=command)

        else:
            route = routes.DELETE_APPLICATION_GUILD_COMMAND.compile(
                application=application, command=command, guild=guild
            )

        await self._request(route)

    async def fetch_application_guild_commands_permissions(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    ) -> typing.Sequence[commands.GuildCommandPermissions]:
        route = routes.GET_APPLICATION_GUILD_COMMANDS_PERMISSIONS.compile(application=application, guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        return [self._entity_factory.deserialize_guild_command_permissions(payload) for payload in response]

    async def fetch_application_command_permissions(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        command: snowflakes.SnowflakeishOr[commands.PartialCommand],
    ) -> commands.GuildCommandPermissions:
        route = routes.GET_APPLICATION_COMMAND_PERMISSIONS.compile(
            application=application, guild=guild, command=command
        )
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_command_permissions(response)

    async def set_application_command_permissions(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        command: snowflakes.SnowflakeishOr[commands.PartialCommand],
        permissions: typing.Sequence[commands.CommandPermission],
    ) -> commands.GuildCommandPermissions:
        route = routes.PUT_APPLICATION_COMMAND_PERMISSIONS.compile(
            application=application, guild=guild, command=command
        )
        body = data_binding.JSONObjectBuilder()
        body.put_array("permissions", permissions, conversion=self._entity_factory.serialize_command_permission)
        response = await self._request(route, json=body)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_command_permissions(response)

    def interaction_deferred_builder(
        self, type_: typing.Union[base_interactions.ResponseType, int], /
    ) -> special_endpoints.InteractionDeferredBuilder:
        return special_endpoints_impl.InteractionDeferredBuilder(type=type_)

    def interaction_autocomplete_builder(
        self, choices: typing.Sequence[commands.CommandChoice]
    ) -> special_endpoints.InteractionAutocompleteBuilder:
        return special_endpoints_impl.InteractionAutocompleteBuilder(choices)

    def interaction_message_builder(
        self, type_: typing.Union[base_interactions.ResponseType, int], /
    ) -> special_endpoints.InteractionMessageBuilder:
        return special_endpoints_impl.InteractionMessageBuilder(type=type_)

    async def fetch_interaction_response(
        self, application: snowflakes.SnowflakeishOr[guilds.PartialApplication], token: str
    ) -> messages_.Message:
        route = routes.GET_INTERACTION_RESPONSE.compile(webhook=application, token=token)
        response = await self._request(route, no_auth=True)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    async def create_interaction_response(
        self,
        interaction: snowflakes.SnowflakeishOr[base_interactions.PartialInteraction],
        token: str,
        response_type: typing.Union[int, base_interactions.ResponseType],
        content: undefined.UndefinedNoneOr[typing.Any] = undefined.UNDEFINED,
        *,
        flags: typing.Union[int, messages_.MessageFlag, undefined.UndefinedType] = undefined.UNDEFINED,
        tts: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedOr[typing.Sequence[special_endpoints.ComponentBuilder]] = undefined.UNDEFINED,
        embed: undefined.UndefinedOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        replace_attachments: bool = False,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
    ) -> None:
        route = routes.POST_INTERACTION_RESPONSE.compile(interaction=interaction, token=token)

        data, form = self._build_message_payload(
            content=content,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            replace_attachments=replace_attachments,
            tts=tts,
            flags=flags,
            mentions_everyone=mentions_everyone,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
        )
        body = data_binding.JSONObjectBuilder()
        body.put("type", response_type)
        body.put("data", data)

        if form is not None:
            form.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
            await self._request(route, form_builder=form, no_auth=True)
        else:
            await self._request(route, json=body, no_auth=True)

    async def edit_interaction_response(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        token: str,
        content: undefined.UndefinedNoneOr[typing.Any] = undefined.UNDEFINED,
        *,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedNoneOr[
            typing.Sequence[special_endpoints.ComponentBuilder]
        ] = undefined.UNDEFINED,
        embed: undefined.UndefinedNoneOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedNoneOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        replace_attachments: bool = False,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
    ) -> messages_.Message:
        route = routes.PATCH_INTERACTION_RESPONSE.compile(webhook=application, token=token)

        body, form_builder = self._build_message_payload(
            content=content,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            replace_attachments=replace_attachments,
            mentions_everyone=mentions_everyone,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
            edit=True,
        )

        if form_builder is not None:
            form_builder.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
            response = await self._request(route, form_builder=form_builder, no_auth=True)
        else:
            response = await self._request(route, json=body, no_auth=True)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    async def delete_interaction_response(
        self, application: snowflakes.SnowflakeishOr[guilds.PartialApplication], token: str
    ) -> None:
        route = routes.DELETE_INTERACTION_RESPONSE.compile(webhook=application, token=token)
        await self._request(route, no_auth=True)

    async def create_autocomplete_response(
        self,
        interaction: snowflakes.SnowflakeishOr[base_interactions.PartialInteraction],
        token: str,
        choices: typing.Sequence[commands.CommandChoice],
    ) -> None:
        route = routes.POST_INTERACTION_RESPONSE.compile(interaction=interaction, token=token)

        body = data_binding.JSONObjectBuilder()
        body.put("type", base_interactions.ResponseType.AUTOCOMPLETE)

        data = data_binding.JSONObjectBuilder()
        data.put("choices", [{"name": choice.name, "value": choice.value} for choice in choices])

        body.put("data", data)
        await self._request(route, json=body, no_auth=True)

    def build_action_row(self) -> special_endpoints.ActionRowBuilder:
        return special_endpoints_impl.ActionRowBuilder()

    async def fetch_scheduled_event(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        event: snowflakes.SnowflakeishOr[scheduled_events.ScheduledEvent],
        /,
    ) -> scheduled_events.ScheduledEvent:
        route = routes.GET_GUILD_SCHEDULED_EVENT.compile(guild=guild, scheduled_event=event)
        query = data_binding.StringMapBuilder()
        query.put("with_user_count", True)

        response = await self._request(route, query=query)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_scheduled_event(response)

    async def fetch_scheduled_events(
        self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild], /
    ) -> typing.Sequence[scheduled_events.ScheduledEvent]:
        route = routes.GET_GUILD_SCHEDULED_EVENTS.compile(guild=guild)
        query = data_binding.StringMapBuilder()
        query.put("with_user_count", True)

        response = await self._request(route, query=query)

        assert isinstance(response, list)
        return [self._entity_factory.deserialize_scheduled_event(event) for event in response]

    async def _create_or_edit_scheduled_stage(
        self,
        route: routes.CompiledRoute,
        entity_type: undefined.UndefinedNoneOr[typing.Union[int, scheduled_events.ScheduledEventType]],
        name: undefined.UndefinedOr[str],
        *,
        channel: undefined.UndefinedNoneOr[snowflakes.SnowflakeishOr[channels_.PartialChannel]] = undefined.UNDEFINED,
        location: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        start_time: undefined.UndefinedOr[datetime.datetime] = undefined.UNDEFINED,
        description: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
        end_time: undefined.UndefinedNoneOr[datetime.datetime] = undefined.UNDEFINED,
        image: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        privacy_level: undefined.UndefinedOr[
            typing.Union[int, scheduled_events.EventPrivacyLevel]
        ] = undefined.UNDEFINED,
        status: undefined.UndefinedOr[typing.Union[int, scheduled_events.ScheduledEventStatus]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> data_binding.JSONObject:
        body = data_binding.JSONObjectBuilder()
        body.put_snowflake("channel_id", channel)
        body.put("name", name)
        body.put("privacy_level", privacy_level)
        body.put("scheduled_start_time", start_time, conversion=datetime.datetime.isoformat)
        body.put("scheduled_end_time", end_time, conversion=datetime.datetime.isoformat)
        body.put("description", description)
        body.put("entity_type", entity_type)
        body.put("status", status)

        if image is not undefined.UNDEFINED:
            image_resource = files.ensure_resource(image)
            async with image_resource.stream(executor=self._executor) as stream:
                body.put("image", await stream.data_uri())

        if location is not undefined.UNDEFINED:
            body["entity_metadata"] = {"location": location}

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return response

    async def create_external_event(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        /,
        location: str,
        start_time: datetime.datetime,
        end_time: datetime.datetime,
        *,
        description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        image: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        privacy_level: typing.Union[
            int, scheduled_events.EventPrivacyLevel
        ] = scheduled_events.EventPrivacyLevel.GUILD_ONLY,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> scheduled_events.ScheduledExternalEvent:
        route = routes.POST_GUILD_SCHEDULED_EVENT.compile(guild=guild)
        response = await self._create_or_edit_scheduled_stage(
            route,
            scheduled_events.ScheduledEventType.EXTERNAL,
            name,
            location=location,
            start_time=start_time,
            description=description,
            end_time=end_time,
            image=image,
            privacy_level=privacy_level,
            reason=reason,
        )
        return self._entity_factory.deserialize_scheduled_external_event(response)

    async def create_stage_event(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        channel: snowflakes.SnowflakeishOr[channels_.PartialChannel],
        name: str,
        /,
        start_time: datetime.datetime,
        *,
        description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        end_time: undefined.UndefinedOr[datetime.datetime] = undefined.UNDEFINED,
        image: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        privacy_level: typing.Union[
            int, scheduled_events.EventPrivacyLevel
        ] = scheduled_events.EventPrivacyLevel.GUILD_ONLY,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> scheduled_events.ScheduledStageEvent:
        route = routes.POST_GUILD_SCHEDULED_EVENT.compile(guild=guild)
        response = await self._create_or_edit_scheduled_stage(
            route,
            scheduled_events.ScheduledEventType.STAGE_INSTANCE,
            name,
            channel=channel,
            start_time=start_time,
            description=description,
            end_time=end_time,
            image=image,
            privacy_level=privacy_level,
            reason=reason,
        )
        return self._entity_factory.deserialize_scheduled_stage_event(response)

    async def create_voice_event(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        channel: snowflakes.SnowflakeishOr[channels_.PartialChannel],
        name: str,
        /,
        start_time: datetime.datetime,
        *,
        description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        end_time: undefined.UndefinedOr[datetime.datetime] = undefined.UNDEFINED,
        image: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        privacy_level: typing.Union[
            int, scheduled_events.EventPrivacyLevel
        ] = scheduled_events.EventPrivacyLevel.GUILD_ONLY,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> scheduled_events.ScheduledVoiceEvent:
        route = routes.POST_GUILD_SCHEDULED_EVENT.compile(guild=guild)
        response = await self._create_or_edit_scheduled_stage(
            route,
            scheduled_events.ScheduledEventType.VOICE,
            name,
            channel=channel,
            start_time=start_time,
            description=description,
            end_time=end_time,
            image=image,
            privacy_level=privacy_level,
            reason=reason,
        )
        return self._entity_factory.deserialize_scheduled_voice_event(response)

    async def edit_scheduled_event(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        event: snowflakes.SnowflakeishOr[scheduled_events.ScheduledEvent],
        /,
        *,
        channel: undefined.UndefinedNoneOr[snowflakes.SnowflakeishOr[channels_.PartialChannel]] = undefined.UNDEFINED,
        description: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
        entity_type: undefined.UndefinedOr[
            typing.Union[int, scheduled_events.ScheduledEventType]
        ] = undefined.UNDEFINED,
        image: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        location: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        privacy_level: undefined.UndefinedOr[
            typing.Union[int, scheduled_events.EventPrivacyLevel]
        ] = undefined.UNDEFINED,
        start_time: undefined.UndefinedOr[datetime.datetime] = undefined.UNDEFINED,
        end_time: undefined.UndefinedNoneOr[datetime.datetime] = undefined.UNDEFINED,
        status: undefined.UndefinedOr[typing.Union[int, scheduled_events.ScheduledEventStatus]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> scheduled_events.ScheduledEvent:
        route = routes.PATCH_GUILD_SCHEDULED_EVENT.compile(guild=guild, scheduled_event=event)

        if entity_type is not undefined.UNDEFINED:
            entity_type = scheduled_events.ScheduledEventType(entity_type)

            # Yes this does have to be explicitly set to None when changing to EXTERNAL
            if entity_type is scheduled_events.ScheduledEventType.EXTERNAL and channel is undefined.UNDEFINED:
                channel = None

        response = await self._create_or_edit_scheduled_stage(
            route,
            entity_type,
            name,
            channel=channel,
            start_time=start_time,
            description=description,
            end_time=end_time,
            image=image,
            location=location,
            privacy_level=privacy_level,
            status=status,
            reason=reason,
        )
        return self._entity_factory.deserialize_scheduled_event(response)

    async def delete_scheduled_event(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        event: snowflakes.SnowflakeishOr[scheduled_events.ScheduledEvent],
        /,
    ) -> None:
        route = routes.DELETE_GUILD_SCHEDULED_EVENT.compile(guild=guild, scheduled_event=event)

        await self._request(route)

    def fetch_scheduled_event_users(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        event: snowflakes.SnowflakeishOr[scheduled_events.ScheduledEvent],
        /,
        *,
        newest_first: bool = False,
        start_at: undefined.UndefinedOr[snowflakes.SearchableSnowflakeishOr[users.PartialUser]] = undefined.UNDEFINED,
    ) -> iterators.LazyIterator[scheduled_events.ScheduledEventUser]:
        if start_at is undefined.UNDEFINED:
            start_at = snowflakes.Snowflake.max() if newest_first else snowflakes.Snowflake.min()
        elif isinstance(start_at, datetime.datetime):
            start_at = snowflakes.Snowflake.from_datetime(start_at)
        else:
            start_at = int(start_at)

        return special_endpoints_impl.ScheduledEventUserIterator(
            self._entity_factory, self._request, newest_first, str(start_at), guild, event
        )

Classes

class ClientCredentialsStrategy

class ClientCredentialsStrategy (
    client: snowflakes.SnowflakeishOr[guilds.PartialApplication],
    client_secret: str,
    *,
    scopes: Sequence[Union[applications.OAuth2Scopestr]] = (<OAuth2Scope.APPLICATIONS_COMMANDS_UPDATE: 'applications.commands.update'>, <OAuth2Scope.IDENTIFY: 'identify'>),
): ...

Strategy class for handling client credential OAuth2 authorization.

Parameters

client : Optional[snowflakes.SnowflakeishOr[guilds.PartialApplication]]
Object or ID of the application this client credentials strategy should authorize as.
client_secret : Optional[str]
Client secret to use when authorizing.

Other Parameters

scopes : Sequence[str]
The scopes to authorize for.
Expand source code
Browse git
class ClientCredentialsStrategy(rest_api.TokenStrategy):
    """Strategy class for handling client credential OAuth2 authorization.

    Parameters
    ----------
    client: typing.Optional[snowflakes.SnowflakeishOr[guilds.PartialApplication]]
        Object or ID of the application this client credentials strategy should
        authorize as.
    client_secret : typing.Optional[builtins.str]
        Client secret to use when authorizing.

    Other Parameters
    ----------------
    scopes : typing.Sequence[str]
        The scopes to authorize for.
    """

    __slots__: typing.Sequence[str] = (
        "_client_id",
        "_client_secret",
        "_exception",
        "_expire_at",
        "_lock",
        "_scopes",
        "_token",
    )

    def __init__(
        self,
        client: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        client_secret: str,
        *,
        scopes: typing.Sequence[typing.Union[applications.OAuth2Scope, str]] = (
            applications.OAuth2Scope.APPLICATIONS_COMMANDS_UPDATE,
            applications.OAuth2Scope.IDENTIFY,
        ),
    ) -> None:
        self._client_id = snowflakes.Snowflake(client)
        self._client_secret = client_secret
        self._exception: typing.Optional[errors.ClientHTTPResponseError] = None
        self._expire_at = 0.0
        self._lock = asyncio.Lock()
        self._scopes = tuple(scopes)
        self._token: typing.Optional[str] = None

    @property
    def client_id(self) -> snowflakes.Snowflake:
        """ID of the application this token strategy authenticates with.

        Returns
        -------
        hikari.snowflakes.Snowflake
            ID of the application this token strategy authenticates with.
        """
        return self._client_id

    @property
    def _is_expired(self) -> bool:
        return time.monotonic() >= self._expire_at

    @property
    def scopes(self) -> typing.Sequence[typing.Union[applications.OAuth2Scope, str]]:
        """Scopes this token strategy authenticates for.

        Returns
        -------
        typing.Sequence[typing.Union[hikari.applications.OAuth2Scope, builtins.str]]
            The scopes this token strategy authenticates for.
        """
        return self._scopes

    @property
    def token_type(self) -> applications.TokenType:
        return applications.TokenType.BEARER

    async def acquire(self, client: rest_api.RESTClient) -> str:
        if self._token and not self._is_expired:
            return self._token

        async with self._lock:
            if self._token and not self._is_expired:
                return self._token

            if self._exception:
                # If we don't copy the exception then python keeps adding onto the stack each time it's raised.
                raise copy.copy(self._exception) from None

            try:
                response = await client.authorize_client_credentials_token(
                    client=self._client_id, client_secret=self._client_secret, scopes=self._scopes
                )

            except errors.ClientHTTPResponseError as exc:
                if not isinstance(exc, errors.RateLimitedError):
                    # If we don't copy the exception then python keeps adding onto the stack each time it's raised.
                    self._exception = copy.copy(exc)

                raise

            # Expires in is lowered a bit in-order to lower the chance of a dead token being used.
            self._expire_at = time.monotonic() + math.floor(response.expires_in.total_seconds() * 0.99)
            self._token = f"{response.token_type} {response.access_token}"
            return self._token

    def invalidate(self, token: typing.Optional[str]) -> None:
        if not token or token == self._token:
            self._expire_at = 0.0
            self._token = None
Method resolution order
class ClientCredentialsStrategy
That's this class!
abstract class TokenStrategy

Interface of an object used for managing OAuth2 access.

extern class abc.ABC

Helper class that provides a standard way to create an ABC using inheritance.

Variables and properties
property client_idSnowflake

ID of the application this token strategy authenticates with.

Returns

Snowflake
ID of the application this token strategy authenticates with.
property scopes : Sequence[Union[OAuth2Scopestr]]

Scopes this token strategy authenticates for.

Returns

Sequence[Union[OAuth2Scope, str]]
The scopes this token strategy authenticates for.
property token_typeTokenType

Type of token this strategy returns.

Returns

Union[TokenType, str]
The type of token this strategy returns.
Methods
async def acquire(
    client: rest_api.RESTClient,
) -> str: ...

Inherited from: TokenStrategy.acquire

Acquire an authorization token (including the prefix).

Returns

str
The current authorization token to use for this client and it's prefix.
Expand source code
Browse git
async def acquire(self, client: rest_api.RESTClient) -> str:
    if self._token and not self._is_expired:
        return self._token

    async with self._lock:
        if self._token and not self._is_expired:
            return self._token

        if self._exception:
            # If we don't copy the exception then python keeps adding onto the stack each time it's raised.
            raise copy.copy(self._exception) from None

        try:
            response = await client.authorize_client_credentials_token(
                client=self._client_id, client_secret=self._client_secret, scopes=self._scopes
            )

        except errors.ClientHTTPResponseError as exc:
            if not isinstance(exc, errors.RateLimitedError):
                # If we don't copy the exception then python keeps adding onto the stack each time it's raised.
                self._exception = copy.copy(exc)

            raise

        # Expires in is lowered a bit in-order to lower the chance of a dead token being used.
        self._expire_at = time.monotonic() + math.floor(response.expires_in.total_seconds() * 0.99)
        self._token = f"{response.token_type} {response.access_token}"
        return self._token
def invalidate(
    token: Optional[str],
) -> None: ...

Inherited from: TokenStrategy.invalidate

Invalidate the cached token in this handler.

Note

token may be provided in-order to avoid newly generated tokens from being invalidated due to multiple calls being made by separate subroutines which are handling the same token.

Parameters

token : Optional[str]
The token to specifically invalidate. If provided then this will only invalidate the cached token if it matches this, otherwise it'll be invalidated regardless.
Expand source code
Browse git
def invalidate(self, token: typing.Optional[str]) -> None:
    if not token or token == self._token:
        self._expire_at = 0.0
        self._token = None

class RESTApp

class RESTApp (
    *,
    executor: Optional[concurrent.futures.Executor] = None,
    http_settings: Optional[config_impl.HTTPSettings] = None,
    max_rate_limit: float = 300,
    max_retries: int = 3,
    proxy_settings: Optional[config_impl.ProxySettings] = None,
    url: Optional[str] = None,
): ...

The base for a HTTP-only Discord application.

This comprises of a shared TCP connector connection pool, and can have RESTClientImpl instances for specific credentials acquired from it.

Parameters

executor : Optional[concurrent.futures.Executor]
The executor to use for blocking file IO operations. If None is passed, then the default concurrent.futures.ThreadPoolExecutor for the AbstractEventLoop will be used instead.
http_settings : Optional[HTTPSettings]
HTTP settings to use. Sane defaults are used if this is None.
max_rate_limit : float

Maximum number of seconds to sleep for when rate limited. If a rate limit occurs that is longer than this value, then a RateLimitedError will be raised instead of waiting.

This is provided since some endpoints may respond with non-sensible rate limits.

Defaults to five minutes if unspecified.

max_retries : Optional[int]
Maximum number of times a request will be retried if it fails with a 5xx status. Defaults to 3 if set to None.
proxy_settings : Optional[ProxySettings]
Proxy settings to use. If None then no proxy configuration will be used.
url : Optional[str]
The base URL for the API. You can generally leave this as being None and the correct default API base URL will be generated.

Note

This event loop will be bound to a connector when the first call to acquire is made.

Expand source code
Browse git
class RESTApp(traits.ExecutorAware):
    """The base for a HTTP-only Discord application.

    This comprises of a shared TCP connector connection pool, and can have
    `RESTClientImpl` instances for specific credentials acquired
    from it.

    Parameters
    ----------
    executor : typing.Optional[concurrent.futures.Executor]
        The executor to use for blocking file IO operations. If `builtins.None`
        is passed, then the default `concurrent.futures.ThreadPoolExecutor` for
        the `asyncio.AbstractEventLoop` will be used instead.
    http_settings : typing.Optional[hikari.impl.config.HTTPSettings]
        HTTP settings to use. Sane defaults are used if this is
        `builtins.None`.
    max_rate_limit : builtins.float
        Maximum number of seconds to sleep for when rate limited. If a rate
        limit occurs that is longer than this value, then a
        `hikari.errors.RateLimitedError` will be raised instead of waiting.

        This is provided since some endpoints may respond with non-sensible
        rate limits.

        Defaults to five minutes if unspecified.
    max_retries : typing.Optional[builtins.int]
        Maximum number of times a request will be retried if
        it fails with a `5xx` status. Defaults to 3 if set to `builtins.None`.
    proxy_settings : typing.Optional[hikari.impl.config.ProxySettings]
        Proxy settings to use. If `builtins.None` then no proxy configuration
        will be used.
    url : typing.Optional[builtins.str]
        The base URL for the API. You can generally leave this as being
        `builtins.None` and the correct default API base URL will be generated.

    !!! note
        This event loop will be bound to a connector when the first call
        to `acquire` is made.
    """

    __slots__: typing.Sequence[str] = (
        "_executor",
        "_http_settings",
        "_max_rate_limit",
        "_max_retries",
        "_proxy_settings",
        "_url",
    )

    def __init__(
        self,
        *,
        executor: typing.Optional[concurrent.futures.Executor] = None,
        http_settings: typing.Optional[config_impl.HTTPSettings] = None,
        max_rate_limit: float = 300,
        max_retries: int = 3,
        proxy_settings: typing.Optional[config_impl.ProxySettings] = None,
        url: typing.Optional[str] = None,
    ) -> None:
        self._http_settings = config_impl.HTTPSettings() if http_settings is None else http_settings
        self._proxy_settings = config_impl.ProxySettings() if proxy_settings is None else proxy_settings
        self._executor = executor
        self._max_rate_limit = max_rate_limit
        self._max_retries = max_retries
        self._url = url

    @property
    def executor(self) -> typing.Optional[concurrent.futures.Executor]:
        return self._executor

    @property
    def http_settings(self) -> config_impl.HTTPSettings:
        return self._http_settings

    @property
    def proxy_settings(self) -> config_impl.ProxySettings:
        return self._proxy_settings

    @typing.overload
    def acquire(self, token: typing.Optional[rest_api.TokenStrategy] = None) -> RESTClientImpl:
        ...

    @typing.overload
    def acquire(
        self,
        token: str,
        token_type: typing.Union[str, applications.TokenType] = applications.TokenType.BEARER,
    ) -> RESTClientImpl:
        ...

    def acquire(
        self,
        token: typing.Union[str, rest_api.TokenStrategy, None] = None,
        token_type: typing.Union[str, applications.TokenType, None] = None,
    ) -> RESTClientImpl:
        """Acquire an instance of this REST client.

        !!! note
            The returned REST client should be started before it can be used,
            either by calling `RESTClientImpl.start` or by using it as an
            asynchronous context manager.

        Examples
        --------
        ```py
        rest_app = RESTApp()

        # Using the returned client as a context manager to implicitly start
        # and stop it.
        async with rest_app.acquire("A token", "Bot") as client:
            user = await client.fetch_my_user()
        ```

        Parameters
        ----------
        token : typing.Union[builtins.str, builtins.None, hikari.api.rest.TokenStrategy]
            The bot or bearer token. If no token is to be used,
            this can be undefined.
        token_type : typing.Union[builtins.str, hikari.applications.TokenType, builtins.None]
            The type of token in use. This should only be passed when `builtins.str`
            is passed for `token`, can be `"Bot"` or `"Bearer"` and will be
            defaulted to `"Bearer"` in this situation.

            This should be left as `builtins.None` when either
            `hikari.api.rest.TokenStrategy` or `builtins.None` is passed for
            `token`.

        Returns
        -------
        RESTClientImpl
            An instance of the REST client.

        Raises
        ------
        builtins.ValueError
            If `token_type` is provided when a token strategy is passed for `token`.
        """
        # Since we essentially mimic a fake App instance, we need to make a circular provider.
        # We can achieve this using a lambda. This allows the entity factory to build models that
        # are also REST-aware
        provider = _RESTProvider(lambda: entity_factory, self._executor, lambda: rest_client)
        entity_factory = entity_factory_impl.EntityFactoryImpl(provider)

        if isinstance(token, str):
            token = token.strip()

            if token_type is None:
                token_type = applications.TokenType.BEARER

        rest_client = RESTClientImpl(
            cache=None,
            entity_factory=entity_factory,
            executor=self._executor,
            http_settings=self._http_settings,
            max_rate_limit=self._max_rate_limit,
            max_retries=self._max_retries,
            proxy_settings=self._proxy_settings,
            token=token,
            token_type=token_type,
            rest_url=self._url,
        )

        return rest_client
Method resolution order
class RESTApp
That's this class!
trait ExecutorAware

Structural supertype for an executor-aware object …

trait FastProtocolChecking

An extension to make protocols with faster instance checks …

extern class Protocol

Base class for protocol classes …

extern class Generic

Abstract base class for generic types …

Variables and properties
property executorOptional[concurrent.futures.Executor]

Return the executor to use for blocking operations.

This may return None if the default asyncio thread pool should be used instead.

Returns

Optional[concurrent.futures.Executor]
The executor to use, or None to use the asyncio default instead.
Methods
def acquire(
    token: Union[strrest_api.TokenStrategyNone] = None,
    token_type: Union[strapplications.TokenTypeNone] = None,
) -> RESTClientImpl: ...

Acquire an instance of this REST client.

Note

The returned REST client should be started before it can be used, either by calling start or by using it as an asynchronous context manager.

Examples

rest_app = RESTApp()

# Using the returned client as a context manager to implicitly start
# and stop it.
async with rest_app.acquire("A token", "Bot") as client:
    user = await client.fetch_my_user()

Parameters

token : Union[str, None, TokenStrategy]
The bot or bearer token. If no token is to be used, this can be undefined.
token_type : Union[str, TokenType, None]

The type of token in use. This should only be passed when str is passed for token, can be "Bot" or "Bearer" and will be defaulted to "Bearer" in this situation.

This should be left as None when either TokenStrategy or None is passed for token.

Returns

RESTClientImpl
An instance of the REST client.

Raises

ValueError
If token_type is provided when a token strategy is passed for token.
Expand source code
Browse git
def acquire(
    self,
    token: typing.Union[str, rest_api.TokenStrategy, None] = None,
    token_type: typing.Union[str, applications.TokenType, None] = None,
) -> RESTClientImpl:
    """Acquire an instance of this REST client.

    !!! note
        The returned REST client should be started before it can be used,
        either by calling `RESTClientImpl.start` or by using it as an
        asynchronous context manager.

    Examples
    --------
    ```py
    rest_app = RESTApp()

    # Using the returned client as a context manager to implicitly start
    # and stop it.
    async with rest_app.acquire("A token", "Bot") as client:
        user = await client.fetch_my_user()
    ```

    Parameters
    ----------
    token : typing.Union[builtins.str, builtins.None, hikari.api.rest.TokenStrategy]
        The bot or bearer token. If no token is to be used,
        this can be undefined.
    token_type : typing.Union[builtins.str, hikari.applications.TokenType, builtins.None]
        The type of token in use. This should only be passed when `builtins.str`
        is passed for `token`, can be `"Bot"` or `"Bearer"` and will be
        defaulted to `"Bearer"` in this situation.

        This should be left as `builtins.None` when either
        `hikari.api.rest.TokenStrategy` or `builtins.None` is passed for
        `token`.

    Returns
    -------
    RESTClientImpl
        An instance of the REST client.

    Raises
    ------
    builtins.ValueError
        If `token_type` is provided when a token strategy is passed for `token`.
    """
    # Since we essentially mimic a fake App instance, we need to make a circular provider.
    # We can achieve this using a lambda. This allows the entity factory to build models that
    # are also REST-aware
    provider = _RESTProvider(lambda: entity_factory, self._executor, lambda: rest_client)
    entity_factory = entity_factory_impl.EntityFactoryImpl(provider)

    if isinstance(token, str):
        token = token.strip()

        if token_type is None:
            token_type = applications.TokenType.BEARER

    rest_client = RESTClientImpl(
        cache=None,
        entity_factory=entity_factory,
        executor=self._executor,
        http_settings=self._http_settings,
        max_rate_limit=self._max_rate_limit,
        max_retries=self._max_retries,
        proxy_settings=self._proxy_settings,
        token=token,
        token_type=token_type,
        rest_url=self._url,
    )

    return rest_client

class RESTClientImpl

class RESTClientImpl (
    *,
    cache: Optional[cache_api.MutableCache],
    entity_factory: entity_factory_.EntityFactory,
    executor: Optional[concurrent.futures.Executor],
    http_settings: config_impl.HTTPSettings,
    max_rate_limit: float,
    max_retries: int = 3,
    proxy_settings: config_impl.ProxySettings,
    token: Union[strNonerest_api.TokenStrategy],
    token_type: Union[applications.TokenTypestrNone],
    rest_url: Optional[str],
): ...

Implementation of the V8-compatible Discord HTTP API.

This manages making HTTP/1.1 requests to the API and using the entity factory within the passed application instance to deserialize JSON responses to Pythonic data classes that are used throughout this library.

Parameters

entity_factory : EntityFactory
The entity factory to use.
executor : Optional[concurrent.futures.Executor]
The executor to use for blocking IO. Defaults to the asyncio thread pool if set to None.
max_rate_limit : float

Maximum number of seconds to sleep for when rate limited. If a rate limit occurs that is longer than this value, then a RateLimitedError will be raised instead of waiting.

This is provided since some endpoints may respond with non-sensible rate limits.

max_retries : Optional[int]
Maximum number of times a request will be retried if it fails with a 5xx status. Defaults to 3 if set to None.
token : Union[str, None, TokenStrategy]
The bot or bearer token. If no token is to be used, this can be undefined.
token_type : Union[str, TokenType, None]

The type of token in use. This must be passed when a str is passed for token but and can be "Bot" or "Bearer".

This should be left as None when either TokenStrategy or None is passed for token.

rest_url : str
The HTTP API base URL. This can contain format-string specifiers to interpolate information such as API version in use.

Raises

ValueError
  • If token_type is provided when a token strategy is passed for token.
  • if token_type is left as None when a string is passed for token.
  • If the a value more than 5 is provided for max_retries
Expand source code
Browse git
class RESTClientImpl(rest_api.RESTClient):
    """Implementation of the V8-compatible Discord HTTP API.

    This manages making HTTP/1.1 requests to the API and using the entity
    factory within the passed application instance to deserialize JSON responses
    to Pythonic data classes that are used throughout this library.

    Parameters
    ----------
    entity_factory : hikari.api.entity_factory.EntityFactory
        The entity factory to use.
    executor : typing.Optional[concurrent.futures.Executor]
        The executor to use for blocking IO. Defaults to the `asyncio` thread
        pool if set to `builtins.None`.
    max_rate_limit : builtins.float
        Maximum number of seconds to sleep for when rate limited. If a rate
        limit occurs that is longer than this value, then a
        `hikari.errors.RateLimitedError` will be raised instead of waiting.

        This is provided since some endpoints may respond with non-sensible
        rate limits.
    max_retries : typing.Optional[builtins.int]
        Maximum number of times a request will be retried if
        it fails with a `5xx` status. Defaults to 3 if set to `builtins.None`.
    token : typing.Union[builtins.str, builtins.None, hikari.api.rest.TokenStrategy]
        The bot or bearer token. If no token is to be used,
        this can be undefined.
    token_type : typing.Union[builtins.str, hikari.applications.TokenType, builtins.None]
        The type of token in use. This must be passed when a `builtins.str` is
        passed for `token` but and can be `"Bot"` or `"Bearer"`.

        This should be left as `builtins.None` when either
        `hikari.api.rest.TokenStrategy` or `builtins.None` is passed for
        `token`.
    rest_url : builtins.str
        The HTTP API base URL. This can contain format-string specifiers to
        interpolate information such as API version in use.

    Raises
    ------
    builtins.ValueError
        * If `token_type` is provided when a token strategy is passed for `token`.
        * if `token_type` is left as `builtins.None` when a string is passed for `token`.
        * If the a value more than 5 is provided for `max_retries`
    """

    __slots__: typing.Sequence[str] = (
        "_cache",
        "_entity_factory",
        "_executor",
        "_http_settings",
        "_live_attributes",
        "_max_rate_limit",
        "_max_retries",
        "_proxy_settings",
        "_rest_url",
        "_token",
        "_token_type",
    )

    def __init__(
        self,
        *,
        cache: typing.Optional[cache_api.MutableCache],
        entity_factory: entity_factory_.EntityFactory,
        executor: typing.Optional[concurrent.futures.Executor],
        http_settings: config_impl.HTTPSettings,
        max_rate_limit: float,
        max_retries: int = 3,
        proxy_settings: config_impl.ProxySettings,
        token: typing.Union[str, None, rest_api.TokenStrategy],
        token_type: typing.Union[applications.TokenType, str, None],
        rest_url: typing.Optional[str],
    ) -> None:
        if max_retries > 5:
            raise ValueError("'max_retries' must be below or equal to 5")

        self._cache = cache
        self._entity_factory = entity_factory
        self._executor = executor
        self._http_settings = http_settings
        self._live_attributes: typing.Optional[_LiveAttributes] = None
        self._max_rate_limit = max_rate_limit
        self._max_retries = max_retries
        self._proxy_settings = proxy_settings

        self._token: typing.Union[str, rest_api.TokenStrategy, None] = None
        self._token_type: typing.Optional[str] = None
        if isinstance(token, str):
            if token_type is None:
                raise ValueError("Token type required when a str is passed for `token`")

            self._token = f"{token_type.title()} {token}"
            self._token_type = applications.TokenType(token_type.title())

        elif isinstance(token, rest_api.TokenStrategy):
            if token_type is not None:
                raise ValueError("Token type should be handled by the token strategy")

            self._token = token
            self._token_type = token.token_type

        # While passing files.URL for rest_url is not officially supported, this is still
        # casted to string here to avoid confusing issues passing a URL here could lead to.
        self._rest_url = str(rest_url) if rest_url is not None else urls.REST_API_URL

    @property
    def is_alive(self) -> bool:
        return self._live_attributes is not None

    @property
    def http_settings(self) -> config_impl.HTTPSettings:
        return self._http_settings

    @property
    def proxy_settings(self) -> config_impl.ProxySettings:
        return self._proxy_settings

    @property
    def entity_factory(self) -> entity_factory_.EntityFactory:
        return self._entity_factory

    @property
    def token_type(self) -> typing.Union[str, applications.TokenType, None]:
        return self._token_type

    @typing.final
    async def close(self) -> None:
        """Close the HTTP client and any open HTTP connections."""
        live_attributes = self._get_live_attributes()
        self._live_attributes = None
        await live_attributes.close()

    @typing.final
    def start(self) -> None:
        """Start the HTTP client.

        !!! note
            This must be called within an active event loop.

        Raises
        ------
        RuntimeError
            If this is called in an environment without an active event loop.
        """
        if self._live_attributes:
            raise errors.ComponentStateConflictError("Cannot start a REST Client which is already alive")

        self._live_attributes = _LiveAttributes.build(self._max_rate_limit, self._http_settings, self._proxy_settings)

    def _get_live_attributes(self) -> _LiveAttributes:
        if self._live_attributes:
            return self._live_attributes

        raise errors.ComponentStateConflictError("Cannot use an inactive REST client")

    async def __aenter__(self) -> RESTClientImpl:
        self.start()
        return self

    async def __aexit__(
        self,
        exc_type: typing.Optional[typing.Type[BaseException]],
        exc_val: typing.Optional[BaseException],
        exc_tb: typing.Optional[types.TracebackType],
    ) -> None:
        await self.close()

    # 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[BaseException]],
            exc_val: typing.Optional[BaseException],
            exc_tb: typing.Optional[types.TracebackType],
        ) -> None:
            return None

    @typing.final
    async def _request(
        self,
        compiled_route: routes.CompiledRoute,
        *,
        query: typing.Optional[data_binding.StringMapBuilder] = None,
        form_builder: typing.Optional[data_binding.URLEncodedFormBuilder] = None,
        json: typing.Union[data_binding.JSONObjectBuilder, data_binding.JSONArray, None] = None,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        no_auth: bool = False,
        auth: typing.Optional[str] = None,
    ) -> typing.Union[None, data_binding.JSONObject, data_binding.JSONArray]:
        # Make a ratelimit-protected HTTP request to a JSON endpoint and expect some form
        # of JSON response.
        live_attributes = self._get_live_attributes()
        headers = data_binding.StringMapBuilder()
        headers.setdefault(_USER_AGENT_HEADER, _HTTP_USER_AGENT)

        re_authed = False
        token: typing.Optional[str] = None
        if auth:
            headers[_AUTHORIZATION_HEADER] = auth

        elif not no_auth:
            if isinstance(self._token, str):
                headers[_AUTHORIZATION_HEADER] = self._token

            elif self._token is not None:
                token = await self._token.acquire(self)
                headers[_AUTHORIZATION_HEADER] = token

        # As per the docs, UTF-8 characters are only supported here if it's url-encoded.
        headers.put(_X_AUDIT_LOG_REASON_HEADER, reason, conversion=urllib.parse.quote)

        url = compiled_route.create_url(self._rest_url)

        # This is initiated the first time we hit a 5xx error to save a little memory when nothing goes wrong
        backoff: typing.Optional[rate_limits.ExponentialBackOff] = None
        retry_count = 0

        stack = contextlib.AsyncExitStack()
        trace_logging_enabled = _LOGGER.isEnabledFor(ux.TRACE)
        while True:
            try:
                uuid = time.uuid()
                async with stack:
                    form = await form_builder.build(stack) if form_builder else None

                    await stack.enter_async_context(live_attributes.still_alive().buckets.acquire(compiled_route))
                    # Buckets not using authentication still have a global
                    # rate limit, but it is different from the token one.
                    if not no_auth:
                        await live_attributes.still_alive().global_rate_limit.acquire()

                    if trace_logging_enabled:
                        _LOGGER.log(
                            ux.TRACE,
                            "%s %s %s\n%s",
                            uuid,
                            compiled_route.method,
                            url,
                            self._stringify_http_message(headers, json),
                        )
                        start = time.monotonic()

                    # Make the request.
                    response = await live_attributes.still_alive().client_session.request(
                        compiled_route.method,
                        url,
                        headers=headers,
                        params=query,
                        json=json,
                        data=form,
                        allow_redirects=self._http_settings.max_redirects is not None,
                        max_redirects=self._http_settings.max_redirects,
                        proxy=self._proxy_settings.url,
                        proxy_headers=self._proxy_settings.all_headers,
                    )

                    if trace_logging_enabled:
                        time_taken = (time.monotonic() - start) * 1_000  # pyright: ignore[reportUnboundVariable]
                        _LOGGER.log(
                            ux.TRACE,
                            "%s %s %s in %sms\n%s",
                            uuid,
                            response.status,
                            response.reason,
                            time_taken,
                            self._stringify_http_message(response.headers, await response.read()),
                        )

                    # Ensure we are not rate limited, and update rate limiting headers where appropriate.
                    await self._parse_ratelimits(compiled_route, response, live_attributes)

                # Don't bother processing any further if we got NO CONTENT. There's not anything
                # to check.
                if response.status == http.HTTPStatus.NO_CONTENT:
                    return None

                # Handle the response when everything went good
                if 200 <= response.status < 300:
                    if response.content_type == _APPLICATION_JSON:
                        # Only deserializing here stops Cloudflare shenanigans messing us around.
                        return data_binding.load_json(await response.read())

                    real_url = str(response.real_url)
                    raise errors.HTTPError(f"Expected JSON [{response.content_type=}, {real_url=}]")

                # Handling 5xx errors
                if response.status in _RETRY_ERROR_CODES and retry_count < self._max_retries:
                    if backoff is None:
                        backoff = rate_limits.ExponentialBackOff(maximum=_MAX_BACKOFF_DURATION)

                    sleep_time = next(backoff)
                    _LOGGER.warning(
                        "Received status %s on request, backing off for %.2fs and retrying. Retries remaining: %s",
                        response.status,
                        sleep_time,
                        self._max_retries - retry_count,
                    )
                    retry_count += 1

                    await asyncio.sleep(sleep_time)
                    continue

                # Attempt to re-auth on UNAUTHORIZED if we are using a TokenStrategy
                can_re_auth = response.status == 401 and not (auth or no_auth or re_authed)
                if can_re_auth and isinstance(self._token, rest_api.TokenStrategy):
                    assert token is not None
                    self._token.invalidate(token)
                    token = await self._token.acquire(self)
                    headers[_AUTHORIZATION_HEADER] = token
                    re_authed = True
                    continue

                await self._handle_error_response(response)

            except _RetryRequest:
                continue

    @staticmethod
    @typing.final
    def _stringify_http_message(headers: data_binding.Headers, body: typing.Any) -> str:
        string = "\n".join(
            f"    {name}: {value}" if name != _AUTHORIZATION_HEADER else f"    {name}: **REDACTED TOKEN**"
            for name, value in headers.items()
        )

        if body is not None:
            string += "\n\n    "
            string += body.decode("ascii") if isinstance(body, bytes) else str(body)

        return string

    @staticmethod
    @typing.final
    async def _handle_error_response(response: aiohttp.ClientResponse) -> typing.NoReturn:
        raise await net.generate_error_response(response)

    @typing.final
    async def _parse_ratelimits(
        self, compiled_route: routes.CompiledRoute, response: aiohttp.ClientResponse, live_attributes: _LiveAttributes
    ) -> None:
        # Handle rate limiting.
        resp_headers = response.headers
        limit = int(resp_headers.get(_X_RATELIMIT_LIMIT_HEADER, "1"))
        remaining = int(resp_headers.get(_X_RATELIMIT_REMAINING_HEADER, "1"))
        bucket = resp_headers.get(_X_RATELIMIT_BUCKET_HEADER)
        reset_after = float(resp_headers.get(_X_RATELIMIT_RESET_AFTER_HEADER, "0"))

        if bucket:
            live_attributes.still_alive().buckets.update_rate_limits(
                compiled_route=compiled_route,
                bucket_header=bucket,
                remaining_header=remaining,
                limit_header=limit,
                reset_after=reset_after,
            )

        if response.status != http.HTTPStatus.TOO_MANY_REQUESTS:
            return

        # Discord have started applying ratelimits to operations on some endpoints
        # based on specific fields used in the JSON body.
        # This does not get reflected in the headers. The first we know is when we
        # get a 429.
        # The issue is that we may get the same response if Discord dynamically
        # adjusts the bucket ratelimits.
        #
        # We have no mechanism for handing field-based ratelimits, so if we get
        # to here, but notice remaining is greater than zero, we should just error.
        #
        # Seems Discord may raise this on some other undocumented cases, which
        # is nice of them. Apparently some dude spamming slurs in the Python
        # guild via a leaked webhook URL made people's clients exhibit this
        # behaviour.
        #
        # If we get ratelimited when running more than one bot under the same token,
        # or if the ratelimiting logic goes wrong, we will get a 429 and expect the
        # "remaining" header to be zeroed, or even negative as I don't trust that there
        # isn't some weird edge case here somewhere in Discord's implementation.
        # We can safely retry if this happens as acquiring the bucket will handle
        # this.
        if remaining <= 0:
            _LOGGER.warning(
                "rate limited on bucket %s, maybe you are running more than one bot on this token? Retrying request...",
                bucket,
            )
            raise _RetryRequest

        if response.content_type != _APPLICATION_JSON:
            # We don't know exactly what this could imply. It is likely Cloudflare interfering
            # but I'd rather we just give up than do something resulting in multiple failed
            # requests repeatedly.
            raise errors.HTTPResponseError(
                str(response.real_url),
                http.HTTPStatus.TOO_MANY_REQUESTS,
                response.headers,
                await response.read(),
                f"received rate limited response with unexpected response type {response.content_type}",
            )

        body = await response.json()
        body_retry_after = float(body["retry_after"])

        if body.get("global", False) is True:
            _LOGGER.error(
                "rate limited on the global bucket. You should consider lowering the number of requests you make or "
                "contacting Discord to raise this limit. Backing off and retrying request..."
            )
            live_attributes.still_alive().global_rate_limit.throttle(body_retry_after)
            raise _RetryRequest

        # If the values are within 20% of each other by relativistic tolerance, it is probably
        # safe to retry the request, as they are likely the same value just with some
        # measuring difference. 20% was used as a rounded figure.
        if math.isclose(body_retry_after, reset_after, rel_tol=0.20):
            _LOGGER.error("rate limited on a sub bucket on bucket %s, but it is safe to retry", bucket)
            raise _RetryRequest

        raise errors.RateLimitedError(
            url=str(response.real_url),
            route=compiled_route,
            headers=response.headers,
            raw_body=body,
            retry_after=body_retry_after,
        )

    async def fetch_channel(
        self, channel: snowflakes.SnowflakeishOr[channels_.PartialChannel]
    ) -> channels_.PartialChannel:
        route = routes.GET_CHANNEL.compile(channel=channel)
        response = await self._request(route)
        assert isinstance(response, dict)
        result = self._entity_factory.deserialize_channel(response)

        if self._cache and isinstance(result, channels_.DMChannel):
            self._cache.set_dm_channel_id(result.recipient.id, result.id)

        return result

    async def edit_channel(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
        /,
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        topic: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        video_quality_mode: undefined.UndefinedOr[typing.Union[channels_.VideoQualityMode, int]] = undefined.UNDEFINED,
        user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
        region: undefined.UndefinedNoneOr[typing.Union[voices.VoiceRegion, str]] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Sequence[channels_.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        parent_category: undefined.UndefinedOr[
            snowflakes.SnowflakeishOr[channels_.GuildCategory]
        ] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> channels_.PartialChannel:
        route = routes.PATCH_CHANNEL.compile(channel=channel)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("position", position)
        body.put("topic", topic)
        body.put("nsfw", nsfw)
        body.put("bitrate", bitrate)
        body.put("video_quality_mode", video_quality_mode)
        body.put("user_limit", user_limit)
        body.put("rate_limit_per_user", rate_limit_per_user, conversion=time.timespan_to_int)
        body.put("rtc_region", region, conversion=str)
        body.put_snowflake("parent_id", parent_category)
        body.put_array(
            "permission_overwrites",
            permission_overwrites,
            conversion=self._entity_factory.serialize_permission_overwrite,
        )

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_channel(response)

    async def follow_channel(
        self,
        news_channel: snowflakes.SnowflakeishOr[channels_.GuildNewsChannel],
        target_channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> channels_.ChannelFollow:
        route = routes.POST_CHANNEL_FOLLOWERS.compile(channel=news_channel)
        body = data_binding.JSONObjectBuilder()
        body.put_snowflake("webhook_channel_id", target_channel)

        response = await self._request(route, json=body, reason=reason)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_channel_follow(response)

    async def delete_channel(
        self, channel: snowflakes.SnowflakeishOr[channels_.PartialChannel]
    ) -> channels_.PartialChannel:
        route = routes.DELETE_CHANNEL.compile(channel=channel)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_channel(response)

    async def edit_my_voice_state(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        channel: snowflakes.SnowflakeishOr[channels_.GuildStageChannel],
        *,
        suppress: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        request_to_speak: typing.Union[undefined.UndefinedType, bool, datetime.datetime] = undefined.UNDEFINED,
    ) -> None:
        route = routes.PATCH_MY_GUILD_VOICE_STATE.compile(guild=guild)
        body = data_binding.JSONObjectBuilder()
        body.put_snowflake("channel_id", channel)
        body.put("suppress", suppress)

        if isinstance(request_to_speak, datetime.datetime):
            body.put("request_to_speak_timestamp", request_to_speak.isoformat())

        elif request_to_speak is True:
            body.put("request_to_speak_timestamp", time.utc_datetime().isoformat())

        elif request_to_speak is False:
            body.put("request_to_speak_timestamp", None)

        await self._request(route, json=body)

    async def edit_voice_state(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        channel: snowflakes.SnowflakeishOr[channels_.GuildStageChannel],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        suppress: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> None:
        route = routes.PATCH_GUILD_VOICE_STATE.compile(guild=guild, user=user)
        body = data_binding.JSONObjectBuilder()
        body.put_snowflake("channel_id", channel)
        body.put("suppress", suppress)
        await self._request(route, json=body)

    async def edit_permission_overwrite(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
        target: typing.Union[
            snowflakes.Snowflakeish, users.PartialUser, guilds.PartialRole, channels_.PermissionOverwrite
        ],
        *,
        target_type: undefined.UndefinedOr[typing.Union[channels_.PermissionOverwriteType, int]] = undefined.UNDEFINED,
        allow: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
        deny: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        if target_type is undefined.UNDEFINED:
            if isinstance(target, users.PartialUser):
                target_type = channels_.PermissionOverwriteType.MEMBER
            elif isinstance(target, guilds.Role):
                target_type = channels_.PermissionOverwriteType.ROLE
            elif isinstance(target, channels_.PermissionOverwrite):
                target_type = target.type
            else:
                raise TypeError(
                    "Cannot determine the type of the target to update. Try specifying 'target_type' manually."
                )

        target = target.id if isinstance(target, channels_.PermissionOverwrite) else target
        route = routes.PUT_CHANNEL_PERMISSIONS.compile(channel=channel, overwrite=target)
        body = data_binding.JSONObjectBuilder()
        body.put("type", target_type)
        body.put("allow", allow)
        body.put("deny", deny)
        await self._request(route, json=body, reason=reason)

    async def edit_permission_overwrites(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
        target: typing.Union[
            snowflakes.Snowflakeish, users.PartialUser, guilds.PartialRole, channels_.PermissionOverwrite
        ],
        *,
        target_type: undefined.UndefinedOr[typing.Union[channels_.PermissionOverwriteType, int]] = undefined.UNDEFINED,
        allow: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
        deny: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        """Edit permissions for a specific entity in the given guild channel.

        .. deprecated:: 2.0.0.dev110
            Use `RESTClient.edit_permission_overwrite` instead.

        Parameters
        ----------
        channel : hikari.snowflakes.SnowflakeishOr[hikari.channels.GuildChannel]
            The channel to edit a permission overwrite in. This may be the
            object, or the ID of an existing channel.
        target : typing.Union[hikari.users.PartialUser, hikari.guilds.PartialRole, hikari.channels.PermissionOverwrite, hikari.snowflakes.Snowflakeish]
            The channel overwrite to edit. This may be the object or the ID of an
            existing overwrite.

        Other Parameters
        ----------------
        target_type : hikari.undefined.UndefinedOr[typing.Union[hikari.channels.PermissionOverwriteType, int]]
            If provided, the type of the target to update. If unset, will attempt to get
            the type from `target`.
        allow : hikari.undefined.UndefinedOr[hikari.permissions.Permissions]
            If provided, the new value of all allowed permissions.
        deny : hikari.undefined.UndefinedOr[hikari.permissions.Permissions]
            If provided, the new value of all disallowed permissions.
        reason : hikari.undefined.UndefinedOr[builtins.str]
            If provided, the reason that will be recorded in the audit logs.
            Maximum of 512 characters.

        Raises
        ------
        builtins.TypeError
            If `target_type` is unset and we were unable to determine the type
            from `target`.
        hikari.errors.BadRequestError
            If any of the fields that are passed have an invalid value.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.ForbiddenError
            If you are missing the `MANAGE_PERMISSIONS` permission in the channel.
        hikari.errors.NotFoundError
            If the channel is not found or the target is not found if it is
            a role.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """  # noqa: E501 - Line too long
        deprecation.warn_deprecated(
            "edit_permission_overwrites",
            removal_version="2.0.0.dev113",
            additional_info="Use 'edit_permission_overwrite' instead",
        )
        await self.edit_permission_overwrite(
            channel, target, target_type=target_type, allow=allow, deny=deny, reason=reason
        )

    async def delete_permission_overwrite(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
        target: typing.Union[
            channels_.PermissionOverwrite, guilds.PartialRole, users.PartialUser, snowflakes.Snowflakeish
        ],
    ) -> None:
        route = routes.DELETE_CHANNEL_PERMISSIONS.compile(channel=channel, overwrite=target)
        await self._request(route)

    async def fetch_channel_invites(
        self, channel: snowflakes.SnowflakeishOr[channels_.GuildChannel]
    ) -> typing.Sequence[invites.InviteWithMetadata]:
        route = routes.GET_CHANNEL_INVITES.compile(channel=channel)
        response = await self._request(route)
        assert isinstance(response, list)
        return [self._entity_factory.deserialize_invite_with_metadata(invite_payload) for invite_payload in response]

    async def create_invite(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
        *,
        max_age: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
        max_uses: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        temporary: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        unique: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        target_type: undefined.UndefinedOr[invites.TargetType] = undefined.UNDEFINED,
        target_user: undefined.UndefinedOr[snowflakes.SnowflakeishOr[users.PartialUser]] = undefined.UNDEFINED,
        target_application: undefined.UndefinedOr[
            snowflakes.SnowflakeishOr[guilds.PartialApplication]
        ] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> invites.InviteWithMetadata:
        route = routes.POST_CHANNEL_INVITES.compile(channel=channel)
        body = data_binding.JSONObjectBuilder()
        body.put("max_age", max_age, conversion=time.timespan_to_int)
        body.put("max_uses", max_uses)
        body.put("temporary", temporary)
        body.put("unique", unique)
        body.put("target_type", target_type)
        body.put_snowflake("target_user_id", target_user)
        body.put_snowflake("target_application_id", target_application)
        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_invite_with_metadata(response)

    def trigger_typing(
        self, channel: snowflakes.SnowflakeishOr[channels_.TextableChannel]
    ) -> special_endpoints.TypingIndicator:
        return special_endpoints_impl.TypingIndicator(
            request_call=self._request, channel=channel, rest_closed_event=self._get_live_attributes().closed_event
        )

    async def fetch_pins(
        self, channel: snowflakes.SnowflakeishOr[channels_.TextableChannel]
    ) -> typing.Sequence[messages_.Message]:
        route = routes.GET_CHANNEL_PINS.compile(channel=channel)
        response = await self._request(route)
        assert isinstance(response, list)
        return [self._entity_factory.deserialize_message(message_pl) for message_pl in response]

    async def pin_message(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    ) -> None:
        route = routes.PUT_CHANNEL_PINS.compile(channel=channel, message=message)
        await self._request(route)

    async def unpin_message(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    ) -> None:
        route = routes.DELETE_CHANNEL_PIN.compile(channel=channel, message=message)
        await self._request(route)

    def fetch_messages(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        *,
        before: undefined.UndefinedOr[snowflakes.SearchableSnowflakeishOr[snowflakes.Unique]] = undefined.UNDEFINED,
        after: undefined.UndefinedOr[snowflakes.SearchableSnowflakeishOr[snowflakes.Unique]] = undefined.UNDEFINED,
        around: undefined.UndefinedOr[snowflakes.SearchableSnowflakeishOr[snowflakes.Unique]] = undefined.UNDEFINED,
    ) -> iterators.LazyIterator[messages_.Message]:
        if undefined.count(before, after, around) < 2:
            raise TypeError("Expected no kwargs, or a maximum of one of 'before', 'after', 'around'")

        timestamp: undefined.UndefinedOr[str]

        if before is not undefined.UNDEFINED:
            direction = "before"
            if isinstance(before, datetime.datetime):
                timestamp = str(snowflakes.Snowflake.from_datetime(before))
            else:
                timestamp = str(int(before))
        elif after is not undefined.UNDEFINED:
            direction = "after"
            if isinstance(after, datetime.datetime):
                timestamp = str(snowflakes.Snowflake.from_datetime(after))
            else:
                timestamp = str(int(after))
        elif around is not undefined.UNDEFINED:
            direction = "around"
            if isinstance(around, datetime.datetime):
                timestamp = str(snowflakes.Snowflake.from_datetime(around))
            else:
                timestamp = str(int(around))
        else:
            direction = "before"
            timestamp = undefined.UNDEFINED

        return special_endpoints_impl.MessageIterator(
            entity_factory=self._entity_factory,
            request_call=self._request,
            channel=channel,
            direction=direction,
            first_id=timestamp,
        )

    async def fetch_message(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    ) -> messages_.Message:
        route = routes.GET_CHANNEL_MESSAGE.compile(channel=channel, message=message)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    def _build_message_payload(  # noqa: C901- Function too complex
        self,
        /,
        *,
        content: undefined.UndefinedOr[typing.Any] = undefined.UNDEFINED,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedNoneOr[
            typing.Sequence[special_endpoints.ComponentBuilder]
        ] = undefined.UNDEFINED,
        embed: undefined.UndefinedNoneOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedNoneOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        replace_attachments: bool = False,
        flags: typing.Union[undefined.UndefinedType, int, messages_.MessageFlag] = undefined.UNDEFINED,
        tts: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        mentions_reply: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
        edit: bool = False,
    ) -> typing.Tuple[data_binding.JSONObjectBuilder, typing.Optional[data_binding.URLEncodedFormBuilder]]:
        if not undefined.any_undefined(attachment, attachments):
            raise ValueError("You may only specify one of 'attachment' or 'attachments', not both")

        if not undefined.any_undefined(component, components):
            raise ValueError("You may only specify one of 'component' or 'components', not both")

        if not undefined.any_undefined(embed, embeds):
            raise ValueError("You may only specify one of 'embed' or 'embeds', not both")

        if undefined.all_undefined(embed, embeds) and isinstance(content, embeds_.Embed):
            # Syntactic sugar, common mistake to accidentally send an embed
            # as the content, so let's detect this and fix it for the user.
            embed = content
            content = undefined.UNDEFINED

        elif undefined.all_undefined(attachment, attachments) and isinstance(
            content, (files.Resource, files.RAWISH_TYPES, os.PathLike)
        ):
            # Syntactic sugar, common mistake to accidentally send an attachment
            # as the content, so let's detect this and fix it for the user. This
            # will still then work with normal implicit embed attachments as
            # we work this out later.
            attachment = content
            content = undefined.UNDEFINED

        final_attachments: typing.List[files.Resource[files.AsyncReader]] = []
        if attachment is not undefined.UNDEFINED:
            final_attachments.append(files.ensure_resource(attachment))
        elif attachments is not undefined.UNDEFINED:
            final_attachments.extend([files.ensure_resource(a) for a in attachments])

        serialized_components: undefined.UndefinedOr[typing.List[data_binding.JSONObject]] = undefined.UNDEFINED
        if component is not undefined.UNDEFINED:
            if component is not None:
                serialized_components = [component.build()]
            else:
                serialized_components = []

        elif components is not undefined.UNDEFINED:
            if components is not None:
                serialized_components = [component.build() for component in components]
            else:
                serialized_components = []

        serialized_embeds: undefined.UndefinedOr[data_binding.JSONArray] = undefined.UNDEFINED
        if embed is not undefined.UNDEFINED:
            if embed is not None:
                embed_payload, embed_attachments = self._entity_factory.serialize_embed(embed)
                final_attachments.extend(embed_attachments)
                serialized_embeds = [embed_payload]

            else:
                serialized_embeds = []

        elif embeds is not undefined.UNDEFINED:
            serialized_embeds = []
            if embeds is not None:
                for e in embeds:
                    embed_payload, embed_attachments = self._entity_factory.serialize_embed(e)
                    final_attachments.extend(embed_attachments)
                    serialized_embeds.append(embed_payload)

        body = data_binding.JSONObjectBuilder()
        body.put("content", content, conversion=lambda v: v if v is None else str(v))
        body.put("tts", tts)
        body.put("flags", flags)
        body.put("embeds", serialized_embeds)
        body.put("components", serialized_components)

        if replace_attachments:
            body.put("attachments", None)

        if not edit or not undefined.all_undefined(mentions_everyone, mentions_reply, user_mentions, role_mentions):
            body.put(
                "allowed_mentions",
                mentions.generate_allowed_mentions(mentions_everyone, mentions_reply, user_mentions, role_mentions),
            )

        if final_attachments:
            form_builder = data_binding.URLEncodedFormBuilder(executor=self._executor)

            for i, attachment in enumerate(final_attachments):
                form_builder.add_resource(f"file{i}", attachment)
            return body, form_builder

        return body, None

    async def create_message(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        content: undefined.UndefinedOr[typing.Any] = undefined.UNDEFINED,
        *,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedOr[typing.Sequence[special_endpoints.ComponentBuilder]] = undefined.UNDEFINED,
        embed: undefined.UndefinedOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        tts: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        reply: undefined.UndefinedOr[snowflakes.SnowflakeishOr[messages_.PartialMessage]] = undefined.UNDEFINED,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        mentions_reply: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
    ) -> messages_.Message:
        route = routes.POST_CHANNEL_MESSAGES.compile(channel=channel)
        body, form_builder = self._build_message_payload(
            content=content,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            tts=tts,
            mentions_everyone=mentions_everyone,
            mentions_reply=mentions_reply,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
        )
        body.put("message_reference", reply, conversion=lambda m: {"message_id": str(int(m))})

        if form_builder is not None:
            form_builder.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
            response = await self._request(route, form_builder=form_builder)
        else:
            response = await self._request(route, json=body)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    async def crosspost_message(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.GuildNewsChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    ) -> messages_.Message:
        route = routes.POST_CHANNEL_CROSSPOST.compile(channel=channel, message=message)

        response = await self._request(route)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    async def edit_message(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
        content: undefined.UndefinedOr[typing.Any] = undefined.UNDEFINED,
        *,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedNoneOr[
            typing.Sequence[special_endpoints.ComponentBuilder]
        ] = undefined.UNDEFINED,
        embed: undefined.UndefinedNoneOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedNoneOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        replace_attachments: bool = False,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        mentions_reply: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
        flags: typing.Union[undefined.UndefinedType, int, messages_.MessageFlag] = undefined.UNDEFINED,
    ) -> messages_.Message:
        route = routes.PATCH_CHANNEL_MESSAGE.compile(channel=channel, message=message)
        body, form_builder = self._build_message_payload(
            content=content,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            replace_attachments=replace_attachments,
            flags=flags,
            mentions_everyone=mentions_everyone,
            mentions_reply=mentions_reply,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
            edit=True,
        )

        if form_builder is not None:
            form_builder.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
            response = await self._request(route, form_builder=form_builder)
        else:
            response = await self._request(route, json=body)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    async def delete_message(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    ) -> None:
        route = routes.DELETE_CHANNEL_MESSAGE.compile(channel=channel, message=message)
        await self._request(route)

    async def delete_messages(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        messages: typing.Union[
            snowflakes.SnowflakeishOr[messages_.PartialMessage],
            snowflakes.SnowflakeishIterable[messages_.PartialMessage],
        ],
        /,
        *other_messages: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    ) -> None:
        route = routes.POST_DELETE_CHANNEL_MESSAGES_BULK.compile(channel=channel)

        pending: typing.List[snowflakes.SnowflakeishOr[messages_.PartialMessage]] = []
        deleted: typing.List[snowflakes.SnowflakeishOr[messages_.PartialMessage]] = []

        if isinstance(messages, typing.Iterable):  # Syntactic sugar. Allows to use iterables
            pending.extend(messages)

        else:
            pending.append(messages)

        # This maintains the order in-order to keep a predictable deletion order.
        pending.extend(other_messages)

        while pending:
            # Discord only allows 2-100 messages in the BULK_DELETE endpoint. Because of that,
            # if the user wants 101 messages deleted, we will post 100 messages in bulk delete
            # and then the last message in a normal delete.
            # Along with this, the bucket size for v6 and v7 seems to be a bit restrictive. As of
            # 30th July 2020, this endpoint returned the following headers when being ratelimited:
            #       x-ratelimit-bucket         b05c0d8c2ab83895085006a8eae073a3
            #       x-ratelimit-limit          1
            #       x-ratelimit-remaining      0
            #       x-ratelimit-reset          1596033974.096
            #       x-ratelimit-reset-after    3.000
            # This kind of defeats the point of asynchronously gathering any of these
            # in the first place really. To save clogging up the event loop
            # (albeit at a cost of maybe a couple-dozen milliseconds per call),
            # I am just gonna invoke these sequentially instead.
            try:
                if len(pending) == 1:
                    message = pending[0]
                    try:
                        await self.delete_message(channel, message)
                    except errors.NotFoundError as exc:
                        # If the message is not found then this error should be suppressed
                        # to keep consistency with how the bulk delete endpoint functions.
                        if exc.code != 10008:  # Unknown Message
                            raise

                    deleted.append(message)

                else:
                    body = data_binding.JSONObjectBuilder()
                    chunk = pending[:100]
                    body.put_snowflake_array("messages", chunk)
                    await self._request(route, json=body)
                    deleted += chunk

                pending = pending[100:]
            except Exception as ex:
                raise errors.BulkDeleteError(deleted, pending) from ex

    @staticmethod
    def _transform_emoji_to_url_format(
        emoji: typing.Union[str, emojis.Emoji],
        emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]],
        /,
    ) -> str:
        if isinstance(emoji, emojis.Emoji):
            if emoji_id is not undefined.UNDEFINED:
                raise ValueError("emoji_id shouldn't be passed when an Emoji object is passed for emoji")

            return emoji.url_name

        if emoji_id is not undefined.UNDEFINED:
            return f"{emoji}:{snowflakes.Snowflake(emoji_id)}"

        return emoji

    async def add_reaction(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
        emoji: typing.Union[str, emojis.Emoji],
        emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = undefined.UNDEFINED,
    ) -> None:
        route = routes.PUT_MY_REACTION.compile(
            emoji=self._transform_emoji_to_url_format(emoji, emoji_id),
            channel=channel,
            message=message,
        )
        await self._request(route)

    async def delete_my_reaction(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
        emoji: typing.Union[str, emojis.Emoji],
        emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = undefined.UNDEFINED,
    ) -> None:
        route = routes.DELETE_MY_REACTION.compile(
            emoji=self._transform_emoji_to_url_format(emoji, emoji_id),
            channel=channel,
            message=message,
        )
        await self._request(route)

    async def delete_all_reactions_for_emoji(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
        emoji: typing.Union[str, emojis.Emoji],
        emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = undefined.UNDEFINED,
    ) -> None:
        route = routes.DELETE_REACTION_EMOJI.compile(
            emoji=self._transform_emoji_to_url_format(emoji, emoji_id),
            channel=channel,
            message=message,
        )
        await self._request(route)

    async def delete_reaction(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        emoji: typing.Union[str, emojis.Emoji],
        emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = undefined.UNDEFINED,
    ) -> None:
        route = routes.DELETE_REACTION_USER.compile(
            emoji=self._transform_emoji_to_url_format(emoji, emoji_id),
            channel=channel,
            message=message,
            user=user,
        )
        await self._request(route)

    async def delete_all_reactions(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    ) -> None:
        route = routes.DELETE_ALL_REACTIONS.compile(channel=channel, message=message)
        await self._request(route)

    def fetch_reactions_for_emoji(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
        emoji: typing.Union[str, emojis.Emoji],
        emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = undefined.UNDEFINED,
    ) -> iterators.LazyIterator[users.User]:
        return special_endpoints_impl.ReactorIterator(
            entity_factory=self._entity_factory,
            request_call=self._request,
            channel=channel,
            message=message,
            emoji=self._transform_emoji_to_url_format(emoji, emoji_id),
        )

    async def create_webhook(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.WebhookChannelT],
        name: str,
        *,
        avatar: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> webhooks.IncomingWebhook:
        route = routes.POST_CHANNEL_WEBHOOKS.compile(channel=channel)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)

        if avatar is not undefined.UNDEFINED:
            avatar_resource = files.ensure_resource(avatar)
            async with avatar_resource.stream(executor=self._executor) as stream:
                body.put("avatar", await stream.data_uri())

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_incoming_webhook(response)

    async def fetch_webhook(
        self,
        webhook: snowflakes.SnowflakeishOr[webhooks.PartialWebhook],
        *,
        token: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> webhooks.PartialWebhook:
        if token is undefined.UNDEFINED:
            route = routes.GET_WEBHOOK.compile(webhook=webhook)
            no_auth = False
        else:
            route = routes.GET_WEBHOOK_WITH_TOKEN.compile(webhook=webhook, token=token)
            no_auth = True

        response = await self._request(route, no_auth=no_auth)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_webhook(response)

    async def fetch_channel_webhooks(
        self,
        channel: snowflakes.SnowflakeishOr[channels_.WebhookChannelT],
    ) -> typing.Sequence[webhooks.PartialWebhook]:
        route = routes.GET_CHANNEL_WEBHOOKS.compile(channel=channel)
        response = await self._request(route)
        assert isinstance(response, list)
        return [self._entity_factory.deserialize_webhook(webhook_pl) for webhook_pl in response]

    async def fetch_guild_webhooks(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    ) -> typing.Sequence[webhooks.PartialWebhook]:
        route = routes.GET_GUILD_WEBHOOKS.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        return [self._entity_factory.deserialize_webhook(webhook_payload) for webhook_payload in response]

    async def edit_webhook(
        self,
        webhook: snowflakes.SnowflakeishOr[webhooks.PartialWebhook],
        *,
        token: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        avatar: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
        channel: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.WebhookChannelT]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> webhooks.PartialWebhook:
        if token is undefined.UNDEFINED:
            route = routes.PATCH_WEBHOOK.compile(webhook=webhook)
            no_auth = False
        else:
            route = routes.PATCH_WEBHOOK_WITH_TOKEN.compile(webhook=webhook, token=token)
            no_auth = True

        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put_snowflake("channel", channel)

        if avatar is None:
            body.put("avatar", None)
        elif avatar is not undefined.UNDEFINED:
            avatar_resource = files.ensure_resource(avatar)
            async with avatar_resource.stream(executor=self._executor) as stream:
                body.put("avatar", await stream.data_uri())

        response = await self._request(route, json=body, reason=reason, no_auth=no_auth)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_webhook(response)

    async def delete_webhook(
        self,
        webhook: snowflakes.SnowflakeishOr[webhooks.PartialWebhook],
        *,
        token: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        if token is undefined.UNDEFINED:
            route = routes.DELETE_WEBHOOK.compile(webhook=webhook)
            no_auth = False
        else:
            route = routes.DELETE_WEBHOOK_WITH_TOKEN.compile(webhook=webhook, token=token)
            no_auth = True

        await self._request(route, no_auth=no_auth)

    async def execute_webhook(
        self,
        webhook: typing.Union[webhooks.ExecutableWebhook, snowflakes.Snowflakeish],
        token: str,
        content: undefined.UndefinedOr[typing.Any] = undefined.UNDEFINED,
        *,
        username: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        avatar_url: typing.Union[undefined.UndefinedType, str, files.URL] = undefined.UNDEFINED,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedOr[typing.Sequence[special_endpoints.ComponentBuilder]] = undefined.UNDEFINED,
        embed: undefined.UndefinedOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        tts: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
        flags: typing.Union[undefined.UndefinedType, int, messages_.MessageFlag] = undefined.UNDEFINED,
    ) -> messages_.Message:
        # int(ExecutableWebhook) isn't guaranteed to be valid nor the ID used to execute this entity as a webhook.
        webhook_id = webhook if isinstance(webhook, int) else webhook.webhook_id
        route = routes.POST_WEBHOOK_WITH_TOKEN.compile(webhook=webhook_id, token=token)

        query = data_binding.StringMapBuilder()
        query.put("wait", True)

        body, form_builder = self._build_message_payload(
            content=content,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            tts=tts,
            flags=flags,
            mentions_everyone=mentions_everyone,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
        )
        body.put("username", username)
        body.put("avatar_url", avatar_url, conversion=str)

        if form_builder is not None:
            form_builder.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
            response = await self._request(route, form_builder=form_builder, query=query, no_auth=True)
        else:
            response = await self._request(route, json=body, query=query, no_auth=True)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    async def fetch_webhook_message(
        self,
        webhook: typing.Union[webhooks.ExecutableWebhook, snowflakes.Snowflakeish],
        token: str,
        message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    ) -> messages_.Message:
        # int(ExecutableWebhook) isn't guaranteed to be valid nor the ID used to execute this entity as a webhook.
        webhook_id = webhook if isinstance(webhook, int) else webhook.webhook_id
        route = routes.GET_WEBHOOK_MESSAGE.compile(webhook=webhook_id, token=token, message=message)
        response = await self._request(route, no_auth=True)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    async def edit_webhook_message(
        self,
        webhook: typing.Union[webhooks.ExecutableWebhook, snowflakes.Snowflakeish],
        token: str,
        message: snowflakes.SnowflakeishOr[messages_.Message],
        content: undefined.UndefinedNoneOr[typing.Any] = undefined.UNDEFINED,
        *,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedNoneOr[
            typing.Sequence[special_endpoints.ComponentBuilder]
        ] = undefined.UNDEFINED,
        embed: undefined.UndefinedNoneOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedNoneOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        replace_attachments: bool = False,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
    ) -> messages_.Message:
        # int(ExecutableWebhook) isn't guaranteed to be valid nor the ID used to execute this entity as a webhook.
        webhook_id = webhook if isinstance(webhook, int) else webhook.webhook_id
        route = routes.PATCH_WEBHOOK_MESSAGE.compile(webhook=webhook_id, token=token, message=message)

        body, form_builder = self._build_message_payload(
            content=content,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            replace_attachments=replace_attachments,
            mentions_everyone=mentions_everyone,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
            edit=True,
        )

        if form_builder is not None:
            form_builder.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
            response = await self._request(route, form_builder=form_builder, no_auth=True)
        else:
            response = await self._request(route, json=body, no_auth=True)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    async def delete_webhook_message(
        self,
        webhook: typing.Union[webhooks.ExecutableWebhook, snowflakes.Snowflakeish],
        token: str,
        message: snowflakes.SnowflakeishOr[messages_.Message],
    ) -> None:
        # int(ExecutableWebhook) isn't guaranteed to be valid nor the ID used to execute this entity as a webhook.
        webhook_id = webhook if isinstance(webhook, int) else webhook.webhook_id
        route = routes.DELETE_WEBHOOK_MESSAGE.compile(webhook=webhook_id, token=token, message=message)
        await self._request(route, no_auth=True)

    async def fetch_gateway_url(self) -> str:
        route = routes.GET_GATEWAY.compile()
        # This doesn't need authorization.
        response = await self._request(route, no_auth=True)
        assert isinstance(response, dict)
        url = response["url"]
        assert isinstance(url, str)
        return url

    async def fetch_gateway_bot_info(self) -> sessions.GatewayBotInfo:
        route = routes.GET_GATEWAY_BOT.compile()
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_gateway_bot_info(response)

    async def fetch_invite(self, invite: typing.Union[invites.InviteCode, str]) -> invites.Invite:
        route = routes.GET_INVITE.compile(invite_code=invite if isinstance(invite, str) else invite.code)
        query = data_binding.StringMapBuilder()
        query.put("with_counts", True)
        query.put("with_expiration", True)
        response = await self._request(route, query=query)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_invite(response)

    async def delete_invite(self, invite: typing.Union[invites.InviteCode, str]) -> invites.Invite:
        route = routes.DELETE_INVITE.compile(invite_code=invite if isinstance(invite, str) else invite.code)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_invite(response)

    async def fetch_my_user(self) -> users.OwnUser:
        route = routes.GET_MY_USER.compile()
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_my_user(response)

    async def edit_my_user(
        self,
        *,
        username: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        avatar: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
    ) -> users.OwnUser:
        route = routes.PATCH_MY_USER.compile()
        body = data_binding.JSONObjectBuilder()
        body.put("username", username)

        if avatar is None:
            body.put("avatar", None)
        elif avatar is not undefined.UNDEFINED:
            avatar_resource = files.ensure_resource(avatar)
            async with avatar_resource.stream(executor=self._executor) as stream:
                body.put("avatar", await stream.data_uri())

        response = await self._request(route, json=body)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_my_user(response)

    async def fetch_my_connections(self) -> typing.Sequence[applications.OwnConnection]:
        route = routes.GET_MY_CONNECTIONS.compile()
        response = await self._request(route)
        assert isinstance(response, list)
        return [self._entity_factory.deserialize_own_connection(connection_payload) for connection_payload in response]

    def fetch_my_guilds(
        self,
        *,
        newest_first: bool = False,
        start_at: undefined.UndefinedOr[snowflakes.SearchableSnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> iterators.LazyIterator[applications.OwnGuild]:
        if start_at is undefined.UNDEFINED:
            start_at = snowflakes.Snowflake.max() if newest_first else snowflakes.Snowflake.min()
        elif isinstance(start_at, datetime.datetime):
            start_at = snowflakes.Snowflake.from_datetime(start_at)
        else:
            start_at = int(start_at)

        return special_endpoints_impl.OwnGuildIterator(
            entity_factory=self._entity_factory,
            request_call=self._request,
            newest_first=newest_first,
            first_id=str(start_at),
        )

    async def leave_guild(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild], /) -> None:
        route = routes.DELETE_MY_GUILD.compile(guild=guild)
        await self._request(route)

    async def create_dm_channel(self, user: snowflakes.SnowflakeishOr[users.PartialUser], /) -> channels_.DMChannel:
        route = routes.POST_MY_CHANNELS.compile()
        body = data_binding.JSONObjectBuilder()
        body.put_snowflake("recipient_id", user)
        response = await self._request(route, json=body)
        assert isinstance(response, dict)
        channel = self._entity_factory.deserialize_dm(response)

        if self._cache:
            self._cache.set_dm_channel_id(user, channel.id)

        return channel

    async def fetch_application(self) -> applications.Application:
        route = routes.GET_MY_APPLICATION.compile()
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_application(response)

    async def fetch_authorization(self) -> applications.AuthorizationInformation:
        route = routes.GET_MY_AUTHORIZATION.compile()
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_authorization_information(response)

    @staticmethod
    def _gen_oauth2_token(client: snowflakes.SnowflakeishOr[guilds.PartialApplication], client_secret: str) -> str:
        token = base64.b64encode(f"{int(client)}:{client_secret}".encode()).decode("utf-8")
        return f"{applications.TokenType.BASIC} {token}"

    async def authorize_client_credentials_token(
        self,
        client: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        client_secret: str,
        scopes: typing.Sequence[typing.Union[applications.OAuth2Scope, str]],
    ) -> applications.PartialOAuth2Token:
        route = routes.POST_TOKEN.compile()
        form_builder = data_binding.URLEncodedFormBuilder()
        form_builder.add_field("grant_type", "client_credentials")
        form_builder.add_field("scope", " ".join(scopes))

        response = await self._request(
            route, form_builder=form_builder, auth=self._gen_oauth2_token(client, client_secret)
        )
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_partial_token(response)

    async def authorize_access_token(
        self,
        client: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        client_secret: str,
        code: str,
        redirect_uri: str,
    ) -> applications.OAuth2AuthorizationToken:
        route = routes.POST_TOKEN.compile()
        form_builder = data_binding.URLEncodedFormBuilder()
        form_builder.add_field("grant_type", "authorization_code")
        form_builder.add_field("code", code)
        form_builder.add_field("redirect_uri", redirect_uri)

        response = await self._request(
            route, form_builder=form_builder, auth=self._gen_oauth2_token(client, client_secret)
        )
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_authorization_token(response)

    async def refresh_access_token(
        self,
        client: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        client_secret: str,
        refresh_token: str,
        *,
        scopes: undefined.UndefinedOr[
            typing.Sequence[typing.Union[applications.OAuth2Scope, str]]
        ] = undefined.UNDEFINED,
    ) -> applications.OAuth2AuthorizationToken:
        route = routes.POST_TOKEN.compile()
        form_builder = data_binding.URLEncodedFormBuilder()
        form_builder.add_field("grant_type", "refresh_token")
        form_builder.add_field("refresh_token", refresh_token)

        if scopes is not undefined.UNDEFINED:
            form_builder.add_field("scope", " ".join(scopes))

        response = await self._request(
            route, form_builder=form_builder, auth=self._gen_oauth2_token(client, client_secret)
        )
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_authorization_token(response)

    async def revoke_access_token(
        self,
        client: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        client_secret: str,
        token: typing.Union[str, applications.PartialOAuth2Token],
    ) -> None:
        route = routes.POST_TOKEN_REVOKE.compile()
        form_builder = data_binding.URLEncodedFormBuilder()
        form_builder.add_field("token", str(token))
        await self._request(route, form_builder=form_builder, auth=self._gen_oauth2_token(client, client_secret))

    async def add_user_to_guild(
        self,
        access_token: typing.Union[str, applications.PartialOAuth2Token],
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        nickname: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        nick: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
        mute: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        deaf: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> typing.Optional[guilds.Member]:
        """Add a user to a guild.

        !!! note
            This requires the `access_token` to have the
            `hikari.applications.OAuth2Scope.GUILDS_JOIN` scope enabled along
            with the authorization of a Bot which has `MANAGE_INVITES`
            permission within the target guild.

        Parameters
        ----------
        access_token : typing.Union[builtins.str, hikari.applications.PartialOAuth2Token]
            Object or string of the access token to use for this request.
        guild : hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]
            The guild to add the user to. This may be the object
            or the ID of an existing guild.
        user : hikari.snowflakes.SnowflakeishOr[hikari.users.PartialUser]
            The user to add to the guild. This may be the object
            or the ID of an existing user.

        Other Parameters
        ----------------
        nickname : hikari.undefined.UndefinedOr[builtins.str]
            If provided, the nick to add to the user when he joins the guild.

            Requires the `MANAGE_NICKNAMES` permission on the guild.
        nick : hikari.undefined.UndefinedNoneOr[builtins.str]
            Deprecated alias for `nickname`.

            .. deprecated:: 2.0.0.dev106
                Use `nickname` instead.
        roles : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishSequence[hikari.guilds.PartialRole]]
            If provided, the roles to add to the user when he joins the guild.
            This may be a collection objects or IDs of existing roles.

            Requires the `MANAGE_ROLES` permission on the guild.
        mute : hikari.undefined.UndefinedOr[builtins.bool]
            If provided, the mute state to add the user when he joins the guild.

            Requires the `MUTE_MEMBERS` permission on the guild.
        deaf : hikari.undefined.UndefinedOr[builtins.bool]
            If provided, the deaf state to add the user when he joins the guild.

            Requires the `DEAFEN_MEMBERS` permission on the guild.

        Returns
        -------
        typing.Optional[hikari.guilds.Member]
            `builtins.None` if the user was already part of the guild, else
            `hikari.guilds.Member`.

        Raises
        ------
        hikari.errors.BadRequestError
            If any of the fields that are passed have an invalid value.
        hikari.errors.ForbiddenError
            If you are not part of the guild you want to add the user to,
            if you are missing permissions to do one of the things you specified,
            if you are using an access token for another user, if the token is
            bound to another bot or if the access token doesn't have the
            `hikari.applications.OAuth2Scope.GUILDS_JOIN` scope enabled.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If you own the guild or the user is not found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        if nick is not undefined.UNDEFINED:
            deprecation.warn_deprecated(
                "nick",
                removal_version="2.0.0.dev113",
                additional_info="Use 'nickname' parameter instead",
            )
            nickname = nick

        route = routes.PUT_GUILD_MEMBER.compile(guild=guild, user=user)
        body = data_binding.JSONObjectBuilder()
        body.put("access_token", str(access_token))
        body.put("nick", nickname)
        body.put("mute", mute)
        body.put("deaf", deaf)
        body.put_snowflake_array("roles", roles)

        if (response := await self._request(route, json=body)) is not None:
            assert isinstance(response, dict)
            return self._entity_factory.deserialize_member(response, guild_id=snowflakes.Snowflake(guild))
        else:
            # User already is in the guild.
            return None

    async def fetch_voice_regions(self) -> typing.Sequence[voices.VoiceRegion]:
        route = routes.GET_VOICE_REGIONS.compile()
        response = await self._request(route)
        assert isinstance(response, list)
        return [
            self._entity_factory.deserialize_voice_region(voice_region_payload) for voice_region_payload in response
        ]

    async def fetch_user(self, user: snowflakes.SnowflakeishOr[users.PartialUser]) -> users.User:
        route = routes.GET_USER.compile(user=user)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_user(response)

    def fetch_audit_log(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        *,
        before: undefined.UndefinedOr[snowflakes.SearchableSnowflakeishOr[snowflakes.Unique]] = undefined.UNDEFINED,
        user: undefined.UndefinedOr[snowflakes.SnowflakeishOr[users.PartialUser]] = undefined.UNDEFINED,
        event_type: undefined.UndefinedOr[typing.Union[audit_logs.AuditLogEventType, int]] = undefined.UNDEFINED,
    ) -> iterators.LazyIterator[audit_logs.AuditLog]:

        timestamp: undefined.UndefinedOr[str]
        if before is undefined.UNDEFINED:
            timestamp = undefined.UNDEFINED
        elif isinstance(before, datetime.datetime):
            timestamp = str(snowflakes.Snowflake.from_datetime(before))
        else:
            timestamp = str(int(before))

        return special_endpoints_impl.AuditLogIterator(
            entity_factory=self._entity_factory,
            request_call=self._request,
            guild=guild,
            before=timestamp,
            user=user,
            action_type=event_type,
        )

    async def fetch_emoji(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        emoji: snowflakes.SnowflakeishOr[emojis.CustomEmoji],
    ) -> emojis.KnownCustomEmoji:
        route = routes.GET_GUILD_EMOJI.compile(guild=guild, emoji=emoji)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_known_custom_emoji(response, guild_id=snowflakes.Snowflake(guild))

    async def fetch_guild_emojis(
        self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]
    ) -> typing.Sequence[emojis.KnownCustomEmoji]:
        route = routes.GET_GUILD_EMOJIS.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        guild_id = snowflakes.Snowflake(guild)
        return [
            self._entity_factory.deserialize_known_custom_emoji(emoji_payload, guild_id=guild_id)
            for emoji_payload in response
        ]

    async def create_emoji(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        image: files.Resourceish,
        *,
        roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> emojis.KnownCustomEmoji:
        route = routes.POST_GUILD_EMOJIS.compile(guild=guild)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        image_resource = files.ensure_resource(image)
        async with image_resource.stream(executor=self._executor) as stream:
            body.put("image", await stream.data_uri())

        body.put_snowflake_array("roles", roles)

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_known_custom_emoji(response, guild_id=snowflakes.Snowflake(guild))

    async def edit_emoji(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        emoji: snowflakes.SnowflakeishOr[emojis.CustomEmoji],
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> emojis.KnownCustomEmoji:
        route = routes.PATCH_GUILD_EMOJI.compile(guild=guild, emoji=emoji)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put_snowflake_array("roles", roles)

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_known_custom_emoji(response, guild_id=snowflakes.Snowflake(guild))

    async def delete_emoji(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        emoji: snowflakes.SnowflakeishOr[emojis.CustomEmoji],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        route = routes.DELETE_GUILD_EMOJI.compile(guild=guild, emoji=emoji)
        await self._request(route, reason=reason)

    async def fetch_available_sticker_packs(self) -> typing.Sequence[stickers.StickerPack]:
        route = routes.GET_STICKER_PACKS.compile()
        response = await self._request(route, no_auth=True)
        assert isinstance(response, dict)
        return [
            self._entity_factory.deserialize_sticker_pack(sticker_pack_payload)
            for sticker_pack_payload in response["sticker_packs"]
        ]

    async def fetch_sticker(
        self,
        sticker: snowflakes.SnowflakeishOr[stickers.PartialSticker],
    ) -> typing.Union[stickers.StandardSticker, stickers.GuildSticker]:
        route = routes.GET_STICKER.compile(sticker=sticker)
        response = await self._request(route)
        assert isinstance(response, dict)
        return (
            self._entity_factory.deserialize_guild_sticker(response)
            if "guild_id" in response
            else self._entity_factory.deserialize_standard_sticker(response)
        )

    async def fetch_guild_stickers(
        self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]
    ) -> typing.Sequence[stickers.GuildSticker]:
        route = routes.GET_GUILD_STICKERS.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        return [
            self._entity_factory.deserialize_guild_sticker(guild_sticker_payload) for guild_sticker_payload in response
        ]

    async def fetch_guild_sticker(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        sticker: snowflakes.SnowflakeishOr[stickers.PartialSticker],
    ) -> stickers.GuildSticker:
        route = routes.GET_GUILD_STICKER.compile(guild=guild, sticker=sticker)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_sticker(response)

    async def create_sticker(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        tag: str,
        image: files.Resourceish,
        *,
        description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> stickers.GuildSticker:
        route = routes.POST_GUILD_STICKERS.compile(guild=guild)
        form = data_binding.URLEncodedFormBuilder(executor=self._executor)
        form.add_field("name", name)
        form.add_field("tags", tag)
        form.add_field("description", description or "")
        form.add_resource("file", files.ensure_resource(image))

        response = await self._request(route, form_builder=form, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_sticker(response)

    async def edit_sticker(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        sticker: snowflakes.SnowflakeishOr[stickers.PartialSticker],
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        tag: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> stickers.GuildSticker:
        route = routes.PATCH_GUILD_STICKER.compile(guild=guild, sticker=sticker)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("tags", tag)
        body.put("description", description)

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_sticker(response)

    async def delete_sticker(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        sticker: snowflakes.SnowflakeishOr[stickers.PartialSticker],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        route = routes.DELETE_GUILD_STICKER.compile(guild=guild, sticker=sticker)
        await self._request(route, reason=reason)

    def guild_builder(self, name: str, /) -> special_endpoints.GuildBuilder:
        return special_endpoints_impl.GuildBuilder(
            entity_factory=self._entity_factory, executor=self._executor, request_call=self._request, name=name
        )

    async def fetch_guild(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> guilds.RESTGuild:
        route = routes.GET_GUILD.compile(guild=guild)
        query = data_binding.StringMapBuilder()
        query.put("with_counts", True)
        response = await self._request(route, query=query)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_rest_guild(response)

    async def fetch_guild_preview(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> guilds.GuildPreview:
        route = routes.GET_GUILD_PREVIEW.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_preview(response)

    async def edit_guild(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        verification_level: undefined.UndefinedOr[guilds.GuildVerificationLevel] = undefined.UNDEFINED,
        default_message_notifications: undefined.UndefinedOr[
            guilds.GuildMessageNotificationsLevel
        ] = undefined.UNDEFINED,
        explicit_content_filter_level: undefined.UndefinedOr[
            guilds.GuildExplicitContentFilterLevel
        ] = undefined.UNDEFINED,
        afk_channel: undefined.UndefinedOr[
            snowflakes.SnowflakeishOr[channels_.GuildVoiceChannel]
        ] = undefined.UNDEFINED,
        afk_timeout: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
        icon: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
        owner: undefined.UndefinedOr[snowflakes.SnowflakeishOr[users.PartialUser]] = undefined.UNDEFINED,
        splash: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
        banner: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
        system_channel: undefined.UndefinedNoneOr[
            snowflakes.SnowflakeishOr[channels_.GuildTextChannel]
        ] = undefined.UNDEFINED,
        rules_channel: undefined.UndefinedNoneOr[
            snowflakes.SnowflakeishOr[channels_.GuildTextChannel]
        ] = undefined.UNDEFINED,
        public_updates_channel: undefined.UndefinedNoneOr[
            snowflakes.SnowflakeishOr[channels_.GuildTextChannel]
        ] = undefined.UNDEFINED,
        preferred_locale: undefined.UndefinedOr[typing.Union[str, locales.Locale]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> guilds.RESTGuild:
        route = routes.PATCH_GUILD.compile(guild=guild)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("verification_level", verification_level)
        body.put("default_message_notifications", default_message_notifications)
        body.put("explicit_content_filter", explicit_content_filter_level)
        body.put("afk_timeout", afk_timeout, conversion=time.timespan_to_int)
        body.put("preferred_locale", preferred_locale, conversion=str)
        body.put_snowflake("afk_channel_id", afk_channel)
        body.put_snowflake("owner_id", owner)
        body.put_snowflake("system_channel_id", system_channel)
        body.put_snowflake("rules_channel_id", rules_channel)
        body.put_snowflake("public_updates_channel_id", public_updates_channel)

        tasks: typing.List[asyncio.Task[str]] = []

        if icon is None:
            body.put("icon", None)
        elif icon is not undefined.UNDEFINED:
            icon_resource = files.ensure_resource(icon)
            async with icon_resource.stream(executor=self._executor) as stream:
                task = asyncio.create_task(stream.data_uri())
                task.add_done_callback(lambda future: body.put("icon", future.result()))
                tasks.append(task)

        if splash is None:
            body.put("splash", None)
        elif splash is not undefined.UNDEFINED:
            splash_resource = files.ensure_resource(splash)
            async with splash_resource.stream(executor=self._executor) as stream:
                task = asyncio.create_task(stream.data_uri())
                task.add_done_callback(lambda future: body.put("splash", future.result()))
                tasks.append(task)

        if banner is None:
            body.put("banner", None)
        elif banner is not undefined.UNDEFINED:
            banner_resource = files.ensure_resource(banner)
            async with banner_resource.stream(executor=self._executor) as stream:
                task = asyncio.create_task(stream.data_uri())
                task.add_done_callback(lambda future: body.put("banner", future.result()))
                tasks.append(task)

        await asyncio.gather(*tasks)

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_rest_guild(response)

    async def delete_guild(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> None:
        route = routes.DELETE_GUILD.compile(guild=guild)
        await self._request(route)

    async def fetch_guild_channels(
        self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]
    ) -> typing.Sequence[channels_.GuildChannel]:
        route = routes.GET_GUILD_CHANNELS.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        channel_sequence = [self._entity_factory.deserialize_channel(channel_payload) for channel_payload in response]
        # Will always be guild channels unless Discord messes up severely on something!
        return typing.cast("typing.Sequence[channels_.GuildChannel]", channel_sequence)

    async def create_guild_text_channel(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        *,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        topic: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Sequence[channels_.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> channels_.GuildTextChannel:
        response = await self._create_guild_channel(
            guild,
            name,
            channels_.ChannelType.GUILD_TEXT,
            position=position,
            topic=topic,
            nsfw=nsfw,
            rate_limit_per_user=rate_limit_per_user,
            permission_overwrites=permission_overwrites,
            category=category,
            reason=reason,
        )
        return self._entity_factory.deserialize_guild_text_channel(response)

    async def create_guild_news_channel(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        *,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        topic: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Sequence[channels_.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> channels_.GuildNewsChannel:
        response = await self._create_guild_channel(
            guild,
            name,
            channels_.ChannelType.GUILD_NEWS,
            position=position,
            topic=topic,
            nsfw=nsfw,
            rate_limit_per_user=rate_limit_per_user,
            permission_overwrites=permission_overwrites,
            category=category,
            reason=reason,
        )
        return self._entity_factory.deserialize_guild_news_channel(response)

    async def create_guild_voice_channel(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        *,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        video_quality_mode: undefined.UndefinedOr[typing.Union[channels_.VideoQualityMode, int]] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Sequence[channels_.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        region: undefined.UndefinedOr[typing.Union[voices.VoiceRegion, str]] = undefined.UNDEFINED,
        category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> channels_.GuildVoiceChannel:
        response = await self._create_guild_channel(
            guild,
            name,
            channels_.ChannelType.GUILD_VOICE,
            position=position,
            user_limit=user_limit,
            bitrate=bitrate,
            video_quality_mode=video_quality_mode,
            permission_overwrites=permission_overwrites,
            region=region,
            category=category,
            reason=reason,
        )
        return self._entity_factory.deserialize_guild_voice_channel(response)

    async def create_guild_stage_channel(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        *,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Sequence[channels_.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        region: undefined.UndefinedOr[typing.Union[voices.VoiceRegion, str]] = undefined.UNDEFINED,
        category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> channels_.GuildStageChannel:
        response = await self._create_guild_channel(
            guild,
            name,
            channels_.ChannelType.GUILD_STAGE,
            position=position,
            user_limit=user_limit,
            bitrate=bitrate,
            permission_overwrites=permission_overwrites,
            region=region,
            category=category,
            reason=reason,
        )
        return self._entity_factory.deserialize_guild_stage_channel(response)

    async def create_guild_category(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        *,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Sequence[channels_.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> channels_.GuildCategory:
        response = await self._create_guild_channel(
            guild,
            name,
            channels_.ChannelType.GUILD_CATEGORY,
            position=position,
            permission_overwrites=permission_overwrites,
            reason=reason,
        )
        return self._entity_factory.deserialize_guild_category(response)

    async def _create_guild_channel(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        type_: channels_.ChannelType,
        *,
        position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        topic: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        video_quality_mode: undefined.UndefinedOr[typing.Union[channels_.VideoQualityMode, int]] = undefined.UNDEFINED,
        user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
        permission_overwrites: undefined.UndefinedOr[
            typing.Sequence[channels_.PermissionOverwrite]
        ] = undefined.UNDEFINED,
        region: undefined.UndefinedOr[typing.Union[voices.VoiceRegion, str]] = undefined.UNDEFINED,
        category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> data_binding.JSONObject:
        route = routes.POST_GUILD_CHANNELS.compile(guild=guild)
        body = data_binding.JSONObjectBuilder()
        body.put("type", type_)
        body.put("name", name)
        body.put("position", position)
        body.put("topic", topic)
        body.put("nsfw", nsfw)
        body.put("bitrate", bitrate)
        body.put("video_quality_mode", video_quality_mode)
        body.put("user_limit", user_limit)
        body.put("rate_limit_per_user", rate_limit_per_user, conversion=time.timespan_to_int)
        body.put("rtc_region", region, conversion=str)
        body.put_snowflake("parent_id", category)
        body.put_array(
            "permission_overwrites",
            permission_overwrites,
            conversion=self._entity_factory.serialize_permission_overwrite,
        )

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return response

    async def reposition_channels(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        positions: typing.Mapping[int, snowflakes.SnowflakeishOr[channels_.GuildChannel]],
    ) -> None:
        route = routes.PATCH_GUILD_CHANNELS.compile(guild=guild)
        body = [{"id": str(int(channel)), "position": pos} for pos, channel in positions.items()]
        await self._request(route, json=body)

    async def fetch_member(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
    ) -> guilds.Member:
        route = routes.GET_GUILD_MEMBER.compile(guild=guild, user=user)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_member(response, guild_id=snowflakes.Snowflake(guild))

    def fetch_members(
        self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]
    ) -> iterators.LazyIterator[guilds.Member]:
        return special_endpoints_impl.MemberIterator(
            entity_factory=self._entity_factory, request_call=self._request, guild=guild
        )

    async def fetch_my_member(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> guilds.Member:
        route = routes.GET_MY_GUILD_MEMBER.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_member(response, guild_id=snowflakes.Snowflake(guild))

    async def search_members(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
    ) -> typing.Sequence[guilds.Member]:
        route = routes.GET_GUILD_MEMBERS_SEARCH.compile(guild=guild)
        query = data_binding.StringMapBuilder()
        query.put("query", name)
        query.put("limit", 1000)
        response = await self._request(route, query=query)
        assert isinstance(response, list)
        guild_id = snowflakes.Snowflake(guild)
        return [
            self._entity_factory.deserialize_member(member_payload, guild_id=guild_id) for member_payload in response
        ]

    async def edit_member(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        nickname: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
        nick: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
        roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
        mute: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        deaf: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        voice_channel: undefined.UndefinedNoneOr[
            snowflakes.SnowflakeishOr[channels_.GuildVoiceChannel]
        ] = undefined.UNDEFINED,
        communication_disabled_until: undefined.UndefinedNoneOr[datetime.datetime] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> guilds.Member:
        """Edit a guild member.

        Parameters
        ----------
        guild : hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]
            The guild to edit. This may be the object
            or the ID of an existing guild.
        user : hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]
            The guild to edit. This may be the object
            or the ID of an existing guild.

        Other Parameters
        ----------------
        nickname : hikari.undefined.UndefinedNoneOr[builtins.str]
            If provided, the new nick for the member. If `builtins.None`,
            will remove the members nick.

            Requires the `MANAGE_NICKNAMES` permission.
        nick : hikari.undefined.UndefinedNoneOr[builtins.str]
            Deprecated alias for `nickname`.

            .. deprecated:: 2.0.0.dev104
                Use `nickname` instead.
        roles : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishSequence[hikari.guilds.PartialRole]]
            If provided, the new roles for the member.

            Requires the `MANAGE_ROLES` permission.
        mute : hikari.undefined.UndefinedOr[builtins.bool]
            If provided, the new server mute state for the member.

            Requires the `MUTE_MEMBERS` permission.
        deaf : hikari.undefined.UndefinedOr[builtins.bool]
            If provided, the new server deaf state for the member.

            Requires the `DEAFEN_MEMBERS` permission.
        voice_channel : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishOr[hikari.channels.GuildVoiceChannel]]]
            If provided, `builtins.None` or the object or the ID of
            an existing voice channel to move the member to.
            If `builtins.None`, will disconnect the member from voice.

            Requires the `MOVE_MEMBERS` permission and the `CONNECT`
            permission in the original voice channel and the target
            voice channel.

            !!! note
                If the member is not in a voice channel, this will
                take no effect.
        communication_disabled_until : hikari.undefined.UndefinedNoneOr[datetime.datetime]
            If provided, the datetime when the timeout (disable communication)
            of the member expires, up to 28 days in the future, or `builtins.None`
            to remove the timeout from the member.

            Requires the `MODERATE_MEMBERS` permission.
        reason : hikari.undefined.UndefinedOr[builtins.str]
            If provided, the reason that will be recorded in the audit logs.
            Maximum of 512 characters.

        Returns
        -------
        hikari.guilds.Member
            Object of the member that was updated.

        Raises
        ------
        hikari.errors.BadRequestError
            If any of the fields that are passed have an invalid value.
        hikari.errors.ForbiddenError
            If you are missing a permission to do an action.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If the guild or the user are not found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        if nick is not undefined.UNDEFINED:
            deprecation.warn_deprecated(
                "nick",
                removal_version="2.0.0.dev113",
                additional_info="Use 'nickname' parameter instead",
            )
            nickname = nick

        route = routes.PATCH_GUILD_MEMBER.compile(guild=guild, user=user)
        body = data_binding.JSONObjectBuilder()
        body.put("nick", nickname)
        body.put("mute", mute)
        body.put("deaf", deaf)
        body.put_snowflake_array("roles", roles)

        if voice_channel is None:
            body.put("channel_id", None)
        else:
            body.put_snowflake("channel_id", voice_channel)

        if isinstance(communication_disabled_until, datetime.datetime):
            body.put("communication_disabled_until", communication_disabled_until.isoformat())
        else:
            body.put("communication_disabled_until", communication_disabled_until)

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_member(response, guild_id=snowflakes.Snowflake(guild))

    async def edit_my_member(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        *,
        nickname: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> guilds.Member:
        route = routes.PATCH_MY_GUILD_MEMBER.compile(guild=guild)
        body = data_binding.JSONObjectBuilder()
        body.put("nick", nickname)

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_member(response, guild_id=snowflakes.Snowflake(guild))

    async def edit_my_nick(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.Guild],
        nick: typing.Optional[str],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        """Edit the associated token's member nick.

        .. deprecated:: 2.0.0.dev104
            Use `RESTClient.edit_my_member`'s `nick` argument instead.

        Parameters
        ----------
        guild : hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]
            The guild to edit. This may be the object
            or the ID of an existing guild.
        nick : typing.Optional[builtins.str]
            The new nick. If `builtins.None`,
            will remove the nick.

        Other Parameters
        ----------------
        reason : hikari.undefined.UndefinedOr[builtins.str]
            If provided, the reason that will be recorded in the audit logs.
            Maximum of 512 characters.

        Raises
        ------
        hikari.errors.ForbiddenError
            If you are missing the `CHANGE_NICKNAME` permission.
        hikari.errors.UnauthorizedError
            If you are unauthorized to make the request (invalid/missing token).
        hikari.errors.NotFoundError
            If the guild is not found.
        hikari.errors.RateLimitTooLongError
            Raised in the event that a rate limit occurs that is
            longer than `max_rate_limit` when making a request.
        hikari.errors.RateLimitedError
            Usually, Hikari will handle and retry on hitting
            rate-limits automatically. This includes most bucket-specific
            rate-limits and global rate-limits. In some rare edge cases,
            however, Discord implements other undocumented rules for
            rate-limiting, such as limits per attribute. These cannot be
            detected or handled normally by Hikari due to their undocumented
            nature, and will trigger this exception if they occur.
        hikari.errors.InternalServerError
            If an internal error occurs on Discord while handling the request.
        """
        deprecation.warn_deprecated(
            "edit_permission_overwrites",
            removal_version="2.0.0.dev113",
            additional_info="Use 'edit_my_member' with the nickname parameter instead.",
        )
        await self.edit_my_member(guild, nickname=nick, reason=reason)

    async def add_role_to_member(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        role: snowflakes.SnowflakeishOr[guilds.PartialRole],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        route = routes.PUT_GUILD_MEMBER_ROLE.compile(guild=guild, user=user, role=role)
        await self._request(route, reason=reason)

    async def remove_role_from_member(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        role: snowflakes.SnowflakeishOr[guilds.PartialRole],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        route = routes.DELETE_GUILD_MEMBER_ROLE.compile(guild=guild, user=user, role=role)
        await self._request(route, reason=reason)

    async def kick_user(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        route = routes.DELETE_GUILD_MEMBER.compile(guild=guild, user=user)
        await self._request(route, reason=reason)

    def kick_member(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> typing.Coroutine[typing.Any, typing.Any, None]:
        return self.kick_user(guild, user, reason=reason)

    async def ban_user(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        delete_message_days: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        body = data_binding.JSONObjectBuilder()
        body.put("delete_message_days", delete_message_days)
        route = routes.PUT_GUILD_BAN.compile(guild=guild, user=user)
        await self._request(route, json=body, reason=reason)

    def ban_member(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        delete_message_days: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> typing.Coroutine[typing.Any, typing.Any, None]:
        return self.ban_user(guild, user, delete_message_days=delete_message_days, reason=reason)

    async def unban_user(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> None:
        route = routes.DELETE_GUILD_BAN.compile(guild=guild, user=user)
        await self._request(route, reason=reason)

    def unban_member(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
        *,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> typing.Coroutine[typing.Any, typing.Any, None]:
        return self.unban_user(guild, user, reason=reason)

    async def fetch_ban(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        user: snowflakes.SnowflakeishOr[users.PartialUser],
    ) -> guilds.GuildBan:
        route = routes.GET_GUILD_BAN.compile(guild=guild, user=user)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_member_ban(response)

    def fetch_bans(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        /,
        *,
        newest_first: bool = False,
        start_at: undefined.UndefinedOr[snowflakes.SearchableSnowflakeishOr[users.PartialUser]] = undefined.UNDEFINED,
    ) -> iterators.LazyIterator[guilds.GuildBan]:
        if start_at is undefined.UNDEFINED:
            start_at = snowflakes.Snowflake.max() if newest_first else snowflakes.Snowflake.min()
        elif isinstance(start_at, datetime.datetime):
            start_at = snowflakes.Snowflake.from_datetime(start_at)
        else:
            start_at = int(start_at)

        return special_endpoints_impl.GuildBanIterator(
            self._entity_factory, self._request, guild, newest_first, str(start_at)
        )

    async def fetch_roles(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    ) -> typing.Sequence[guilds.Role]:
        route = routes.GET_GUILD_ROLES.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        guild_id = snowflakes.Snowflake(guild)
        return [self._entity_factory.deserialize_role(role_payload, guild_id=guild_id) for role_payload in response]

    async def create_role(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        permissions: undefined.UndefinedOr[permissions_.Permissions] = permissions_.Permissions.NONE,
        color: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
        colour: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
        hoist: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        icon: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        unicode_emoji: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        mentionable: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> guilds.Role:
        if not undefined.any_undefined(color, colour):
            raise TypeError("Can not specify 'color' and 'colour' together.")

        if not undefined.any_undefined(icon, unicode_emoji):
            raise TypeError("Can not specify 'icon' and 'unicode_emoji' together.")

        route = routes.POST_GUILD_ROLES.compile(guild=guild)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("permissions", permissions)
        body.put("color", color, conversion=colors.Color.of)
        body.put("color", colour, conversion=colors.Color.of)
        body.put("hoist", hoist)
        body.put("unicode_emoji", unicode_emoji)
        body.put("mentionable", mentionable)

        if icon is not undefined.UNDEFINED:
            icon_resource = files.ensure_resource(icon)
            async with icon_resource.stream(executor=self._executor) as stream:
                body.put("icon", await stream.data_uri())

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_role(response, guild_id=snowflakes.Snowflake(guild))

    async def reposition_roles(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        positions: typing.Mapping[int, snowflakes.SnowflakeishOr[guilds.PartialRole]],
    ) -> None:
        route = routes.PATCH_GUILD_ROLES.compile(guild=guild)
        body = [{"id": str(int(role)), "position": pos} for pos, role in positions.items()]
        await self._request(route, json=body)

    async def edit_role(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        role: snowflakes.SnowflakeishOr[guilds.PartialRole],
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        permissions: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
        color: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
        colour: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
        hoist: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        icon: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
        unicode_emoji: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
        mentionable: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> guilds.Role:
        if not undefined.any_undefined(color, colour):
            raise TypeError("Can not specify 'color' and 'colour' together.")

        if not undefined.any_undefined(icon, unicode_emoji):
            raise TypeError("Can not specify 'icon' and 'unicode_emoji' together.")

        route = routes.PATCH_GUILD_ROLE.compile(guild=guild, role=role)

        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("permissions", permissions)
        body.put("color", color, conversion=colors.Color.of)
        body.put("color", colour, conversion=colors.Color.of)
        body.put("hoist", hoist)
        body.put("unicode_emoji", unicode_emoji)
        body.put("mentionable", mentionable)

        if icon is None:
            body.put("icon", None)
        elif icon is not undefined.UNDEFINED:
            icon_resource = files.ensure_resource(icon)
            async with icon_resource.stream(executor=self._executor) as stream:
                body.put("icon", await stream.data_uri())

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_role(response, guild_id=snowflakes.Snowflake(guild))

    async def delete_role(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        role: snowflakes.SnowflakeishOr[guilds.PartialRole],
    ) -> None:
        route = routes.DELETE_GUILD_ROLE.compile(guild=guild, role=role)
        await self._request(route)

    async def estimate_guild_prune_count(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        *,
        days: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        include_roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
    ) -> int:
        route = routes.GET_GUILD_PRUNE.compile(guild=guild)
        query = data_binding.StringMapBuilder()
        query.put("days", days)
        if include_roles is not undefined.UNDEFINED:
            roles = ",".join(str(int(role)) for role in include_roles)
            query.put("include_roles", roles)
        response = await self._request(route, query=query)
        assert isinstance(response, dict)
        return int(response["pruned"])

    async def begin_guild_prune(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        *,
        days: undefined.UndefinedOr[int] = undefined.UNDEFINED,
        compute_prune_count: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        include_roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> typing.Optional[int]:
        route = routes.POST_GUILD_PRUNE.compile(guild=guild)
        body = data_binding.JSONObjectBuilder()
        body.put("days", days)
        body.put("compute_prune_count", compute_prune_count)
        body.put_snowflake_array("include_roles", include_roles)
        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        pruned = response.get("pruned")
        return int(pruned) if pruned is not None else None

    async def fetch_guild_voice_regions(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    ) -> typing.Sequence[voices.VoiceRegion]:
        route = routes.GET_GUILD_VOICE_REGIONS.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        return [
            self._entity_factory.deserialize_voice_region(voice_region_payload) for voice_region_payload in response
        ]

    async def fetch_guild_invites(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    ) -> typing.Sequence[invites.InviteWithMetadata]:
        route = routes.GET_GUILD_INVITES.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        return [self._entity_factory.deserialize_invite_with_metadata(invite_payload) for invite_payload in response]

    async def fetch_integrations(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    ) -> typing.Sequence[guilds.Integration]:
        route = routes.GET_GUILD_INTEGRATIONS.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        guild_id = snowflakes.Snowflake(guild)
        return [
            self._entity_factory.deserialize_integration(integration_payload, guild_id=guild_id)
            for integration_payload in response
        ]

    async def fetch_widget(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> guilds.GuildWidget:
        route = routes.GET_GUILD_WIDGET.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_widget(response)

    async def edit_widget(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        *,
        channel: undefined.UndefinedNoneOr[snowflakes.SnowflakeishOr[channels_.GuildChannel]] = undefined.UNDEFINED,
        enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> guilds.GuildWidget:
        route = routes.PATCH_GUILD_WIDGET.compile(guild=guild)

        body = data_binding.JSONObjectBuilder()
        body.put("enabled", enabled)
        if channel is None:
            body.put("channel", None)
        elif channel is not undefined.UNDEFINED:
            body.put_snowflake("channel", channel)

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_widget(response)

    async def fetch_welcome_screen(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> guilds.WelcomeScreen:
        route = routes.GET_GUILD_WELCOME_SCREEN.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_welcome_screen(response)

    async def edit_welcome_screen(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        *,
        description: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
        enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        channels: undefined.UndefinedNoneOr[typing.Sequence[guilds.WelcomeChannel]] = undefined.UNDEFINED,
    ) -> guilds.WelcomeScreen:
        route = routes.PATCH_GUILD_WELCOME_SCREEN.compile(guild=guild)

        body = data_binding.JSONObjectBuilder()

        body.put("description", description)
        body.put("enabled", enabled)

        if channels is not None:
            body.put_array("welcome_channels", channels, conversion=self._entity_factory.serialize_welcome_channel)

        else:
            body.put("welcome_channels", None)

        response = await self._request(route, json=body)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_welcome_screen(response)

    async def fetch_vanity_url(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> invites.VanityURL:
        route = routes.GET_GUILD_VANITY_URL.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_vanity_url(response)

    async def fetch_template(self, template: typing.Union[templates.Template, str]) -> templates.Template:
        template = template if isinstance(template, str) else template.code
        route = routes.GET_TEMPLATE.compile(template=template)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_template(response)

    async def fetch_guild_templates(
        self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]
    ) -> typing.Sequence[templates.Template]:
        route = routes.GET_GUILD_TEMPLATES.compile(guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        return [self._entity_factory.deserialize_template(template_payload) for template_payload in response]

    async def sync_guild_template(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        template: typing.Union[templates.Template, str],
    ) -> templates.Template:
        template = template if isinstance(template, str) else template.code
        route = routes.PUT_GUILD_TEMPLATE.compile(guild=guild, template=template)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_template(response)

    async def create_guild_from_template(
        self,
        template: typing.Union[str, templates.Template],
        name: str,
        *,
        icon: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
    ) -> guilds.RESTGuild:
        template = template if isinstance(template, str) else template.code
        route = routes.POST_TEMPLATE.compile(template=template)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)

        if icon is not undefined.UNDEFINED:
            icon_resource = files.ensure_resource(icon)
            async with icon_resource.stream(executor=self._executor) as stream:
                body.put("icon", await stream.data_uri())

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

    async def create_template(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        *,
        description: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
    ) -> templates.Template:
        route = routes.POST_GUILD_TEMPLATES.compile(guild=guild)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("description", description)
        response = await self._request(route, json=body)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_template(response)

    async def edit_template(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        template: typing.Union[str, templates.Template],
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        description: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
    ) -> templates.Template:
        template = template if isinstance(template, str) else template.code
        route = routes.PATCH_GUILD_TEMPLATE.compile(guild=guild, template=template)
        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("description", description)

        response = await self._request(route, json=body)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_template(response)

    async def delete_template(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        template: typing.Union[str, templates.Template],
    ) -> templates.Template:
        template = template if isinstance(template, str) else template.code
        route = routes.DELETE_GUILD_TEMPLATE.compile(guild=guild, template=template)
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_template(response)

    def command_builder(self, name: str, description: str) -> special_endpoints.SlashCommandBuilder:
        r"""Create a slash command builder to use in `RESTClient.set_application_commands`.

        .. deprecated:: 2.0.0.dev106
            Use `RESTClient.slash_command_builder` instead.

        Parameters
        ----------
        name : builtins.str
            The command's name. This should match the regex `^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$` in
            Unicode mode and be lowercase.
        description : builtins.str
            The description to set for the command.
            This should be inclusively between 1-100 characters in length.

        Returns
        -------
        hikari.api.special_endpoints.SlashCommandBuilder
            The created command builder object.
        """
        deprecation.warn_deprecated(
            "command_builder",
            removal_version="2.0.0.dev113",
            additional_info="Use 'slash_command_builder' instead.",
        )
        return self.slash_command_builder(name, description)

    def slash_command_builder(self, name: str, description: str) -> special_endpoints.SlashCommandBuilder:
        return special_endpoints_impl.SlashCommandBuilder(name, description)

    def context_menu_command_builder(
        self,
        type: typing.Union[commands.CommandType, int],
        name: str,
    ) -> special_endpoints.ContextMenuCommandBuilder:
        return special_endpoints_impl.ContextMenuCommandBuilder(commands.CommandType(type), name)

    async def fetch_application_command(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        command: snowflakes.SnowflakeishOr[commands.PartialCommand],
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> commands.PartialCommand:
        if guild is undefined.UNDEFINED:
            route = routes.GET_APPLICATION_COMMAND.compile(application=application, command=command)

        else:
            route = routes.GET_APPLICATION_GUILD_COMMAND.compile(application=application, guild=guild, command=command)

        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_command(
            response, guild_id=snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
        )

    async def fetch_application_commands(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> typing.Sequence[commands.PartialCommand]:
        if guild is undefined.UNDEFINED:
            route = routes.GET_APPLICATION_COMMANDS.compile(application=application)

        else:
            route = routes.GET_APPLICATION_GUILD_COMMANDS.compile(application=application, guild=guild)

        query = data_binding.StringMapBuilder()
        query.put("with_localizations", True)

        response = await self._request(route, query=query)
        assert isinstance(response, list)
        guild_id = snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
        return [self._entity_factory.deserialize_command(command, guild_id=guild_id) for command in response]

    async def _create_application_command(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        type: typing.Union[commands.CommandType, int],
        name: str,
        description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        *,
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
        options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
        name_localizations: undefined.UndefinedOr[
            typing.Mapping[typing.Union[locales.Locale, str], str]
        ] = undefined.UNDEFINED,
        description_localizations: undefined.UndefinedOr[
            typing.Mapping[typing.Union[locales.Locale, str], str]
        ] = undefined.UNDEFINED,
        default_member_permissions: typing.Union[
            undefined.UndefinedType, int, permissions_.Permissions
        ] = undefined.UNDEFINED,
        dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> data_binding.JSONObject:
        if guild is undefined.UNDEFINED:
            route = routes.POST_APPLICATION_COMMAND.compile(application=application)

        else:
            route = routes.POST_APPLICATION_GUILD_COMMAND.compile(application=application, guild=guild)

        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("description", description)
        body.put("type", type)
        body.put_array("options", options, conversion=self._entity_factory.serialize_command_option)
        body.put("name_localizations", name_localizations)
        body.put("description_localizations", description_localizations)

        # Discord has some funky behaviour around what 0 means. They consider it to be the same as ADMINISTRATOR,
        # but we consider it to be the same as None for developer sanity reasons
        body.put("default_member_permissions", None if default_member_permissions == 0 else default_member_permissions)
        body.put("dm_permission", dm_enabled)

        response = await self._request(route, json=body)
        assert isinstance(response, dict)
        return response

    async def create_slash_command(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        name: str,
        description: str,
        *,
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
        options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
        name_localizations: undefined.UndefinedOr[
            typing.Mapping[typing.Union[locales.Locale, str], str]
        ] = undefined.UNDEFINED,
        description_localizations: undefined.UndefinedOr[
            typing.Mapping[typing.Union[locales.Locale, str], str]
        ] = undefined.UNDEFINED,
        default_member_permissions: typing.Union[
            undefined.UndefinedType, int, permissions_.Permissions
        ] = undefined.UNDEFINED,
        dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> commands.SlashCommand:
        response = await self._create_application_command(
            application=application,
            type=commands.CommandType.SLASH,
            name=name,
            description=description,
            guild=guild,
            options=options,
            name_localizations=name_localizations,
            description_localizations=description_localizations,
            default_member_permissions=default_member_permissions,
            dm_enabled=dm_enabled,
        )
        return self._entity_factory.deserialize_slash_command(
            response, guild_id=snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
        )

    async def create_context_menu_command(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        type: typing.Union[commands.CommandType, int],
        name: str,
        *,
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
        name_localizations: undefined.UndefinedOr[
            typing.Mapping[typing.Union[locales.Locale, str], str]
        ] = undefined.UNDEFINED,
        default_member_permissions: typing.Union[
            undefined.UndefinedType, int, permissions_.Permissions
        ] = undefined.UNDEFINED,
        dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> commands.ContextMenuCommand:
        response = await self._create_application_command(
            application=application,
            type=type,
            name=name,
            guild=guild,
            name_localizations=name_localizations,
            default_member_permissions=default_member_permissions,
            dm_enabled=dm_enabled,
        )
        return self._entity_factory.deserialize_context_menu_command(
            response, guild_id=snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
        )

    async def set_application_commands(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        commands: typing.Sequence[special_endpoints.CommandBuilder],
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> typing.Sequence[commands.PartialCommand]:
        if guild is undefined.UNDEFINED:
            route = routes.PUT_APPLICATION_COMMANDS.compile(application=application)

        else:
            route = routes.PUT_APPLICATION_GUILD_COMMANDS.compile(application=application, guild=guild)

        response = await self._request(route, json=[command.build(self._entity_factory) for command in commands])
        assert isinstance(response, list)
        guild_id = snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
        return [self._entity_factory.deserialize_command(payload, guild_id=guild_id) for payload in response]

    async def edit_application_command(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        command: snowflakes.SnowflakeishOr[commands.PartialCommand],
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
        *,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
        default_member_permissions: typing.Union[
            undefined.UndefinedType, int, permissions_.Permissions
        ] = undefined.UNDEFINED,
        dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    ) -> commands.PartialCommand:
        if guild is undefined.UNDEFINED:
            route = routes.PATCH_APPLICATION_COMMAND.compile(application=application, command=command)

        else:
            route = routes.PATCH_APPLICATION_GUILD_COMMAND.compile(
                application=application, command=command, guild=guild
            )

        body = data_binding.JSONObjectBuilder()
        body.put("name", name)
        body.put("description", description)
        body.put_array("options", options, conversion=self._entity_factory.serialize_command_option)
        # Discord has some funky behaviour around what 0 means. They consider it to be the same as ADMINISTRATOR,
        # but we consider it to be the same as None for developer sanity reasons
        body.put("default_member_permissions", None if default_member_permissions == 0 else default_member_permissions)
        body.put("dm_permission", dm_enabled)

        response = await self._request(route, json=body)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_command(
            response, guild_id=snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
        )

    async def delete_application_command(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        command: snowflakes.SnowflakeishOr[commands.PartialCommand],
        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    ) -> None:
        if guild is undefined.UNDEFINED:
            route = routes.DELETE_APPLICATION_COMMAND.compile(application=application, command=command)

        else:
            route = routes.DELETE_APPLICATION_GUILD_COMMAND.compile(
                application=application, command=command, guild=guild
            )

        await self._request(route)

    async def fetch_application_guild_commands_permissions(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    ) -> typing.Sequence[commands.GuildCommandPermissions]:
        route = routes.GET_APPLICATION_GUILD_COMMANDS_PERMISSIONS.compile(application=application, guild=guild)
        response = await self._request(route)
        assert isinstance(response, list)
        return [self._entity_factory.deserialize_guild_command_permissions(payload) for payload in response]

    async def fetch_application_command_permissions(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        command: snowflakes.SnowflakeishOr[commands.PartialCommand],
    ) -> commands.GuildCommandPermissions:
        route = routes.GET_APPLICATION_COMMAND_PERMISSIONS.compile(
            application=application, guild=guild, command=command
        )
        response = await self._request(route)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_command_permissions(response)

    async def set_application_command_permissions(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        command: snowflakes.SnowflakeishOr[commands.PartialCommand],
        permissions: typing.Sequence[commands.CommandPermission],
    ) -> commands.GuildCommandPermissions:
        route = routes.PUT_APPLICATION_COMMAND_PERMISSIONS.compile(
            application=application, guild=guild, command=command
        )
        body = data_binding.JSONObjectBuilder()
        body.put_array("permissions", permissions, conversion=self._entity_factory.serialize_command_permission)
        response = await self._request(route, json=body)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_guild_command_permissions(response)

    def interaction_deferred_builder(
        self, type_: typing.Union[base_interactions.ResponseType, int], /
    ) -> special_endpoints.InteractionDeferredBuilder:
        return special_endpoints_impl.InteractionDeferredBuilder(type=type_)

    def interaction_autocomplete_builder(
        self, choices: typing.Sequence[commands.CommandChoice]
    ) -> special_endpoints.InteractionAutocompleteBuilder:
        return special_endpoints_impl.InteractionAutocompleteBuilder(choices)

    def interaction_message_builder(
        self, type_: typing.Union[base_interactions.ResponseType, int], /
    ) -> special_endpoints.InteractionMessageBuilder:
        return special_endpoints_impl.InteractionMessageBuilder(type=type_)

    async def fetch_interaction_response(
        self, application: snowflakes.SnowflakeishOr[guilds.PartialApplication], token: str
    ) -> messages_.Message:
        route = routes.GET_INTERACTION_RESPONSE.compile(webhook=application, token=token)
        response = await self._request(route, no_auth=True)
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    async def create_interaction_response(
        self,
        interaction: snowflakes.SnowflakeishOr[base_interactions.PartialInteraction],
        token: str,
        response_type: typing.Union[int, base_interactions.ResponseType],
        content: undefined.UndefinedNoneOr[typing.Any] = undefined.UNDEFINED,
        *,
        flags: typing.Union[int, messages_.MessageFlag, undefined.UndefinedType] = undefined.UNDEFINED,
        tts: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedOr[typing.Sequence[special_endpoints.ComponentBuilder]] = undefined.UNDEFINED,
        embed: undefined.UndefinedOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        replace_attachments: bool = False,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
    ) -> None:
        route = routes.POST_INTERACTION_RESPONSE.compile(interaction=interaction, token=token)

        data, form = self._build_message_payload(
            content=content,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            replace_attachments=replace_attachments,
            tts=tts,
            flags=flags,
            mentions_everyone=mentions_everyone,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
        )
        body = data_binding.JSONObjectBuilder()
        body.put("type", response_type)
        body.put("data", data)

        if form is not None:
            form.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
            await self._request(route, form_builder=form, no_auth=True)
        else:
            await self._request(route, json=body, no_auth=True)

    async def edit_interaction_response(
        self,
        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
        token: str,
        content: undefined.UndefinedNoneOr[typing.Any] = undefined.UNDEFINED,
        *,
        attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
        component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
        components: undefined.UndefinedNoneOr[
            typing.Sequence[special_endpoints.ComponentBuilder]
        ] = undefined.UNDEFINED,
        embed: undefined.UndefinedNoneOr[embeds_.Embed] = undefined.UNDEFINED,
        embeds: undefined.UndefinedNoneOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
        replace_attachments: bool = False,
        mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
        user_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
        ] = undefined.UNDEFINED,
        role_mentions: undefined.UndefinedOr[
            typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
        ] = undefined.UNDEFINED,
    ) -> messages_.Message:
        route = routes.PATCH_INTERACTION_RESPONSE.compile(webhook=application, token=token)

        body, form_builder = self._build_message_payload(
            content=content,
            attachment=attachment,
            attachments=attachments,
            component=component,
            components=components,
            embed=embed,
            embeds=embeds,
            replace_attachments=replace_attachments,
            mentions_everyone=mentions_everyone,
            user_mentions=user_mentions,
            role_mentions=role_mentions,
            edit=True,
        )

        if form_builder is not None:
            form_builder.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
            response = await self._request(route, form_builder=form_builder, no_auth=True)
        else:
            response = await self._request(route, json=body, no_auth=True)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_message(response)

    async def delete_interaction_response(
        self, application: snowflakes.SnowflakeishOr[guilds.PartialApplication], token: str
    ) -> None:
        route = routes.DELETE_INTERACTION_RESPONSE.compile(webhook=application, token=token)
        await self._request(route, no_auth=True)

    async def create_autocomplete_response(
        self,
        interaction: snowflakes.SnowflakeishOr[base_interactions.PartialInteraction],
        token: str,
        choices: typing.Sequence[commands.CommandChoice],
    ) -> None:
        route = routes.POST_INTERACTION_RESPONSE.compile(interaction=interaction, token=token)

        body = data_binding.JSONObjectBuilder()
        body.put("type", base_interactions.ResponseType.AUTOCOMPLETE)

        data = data_binding.JSONObjectBuilder()
        data.put("choices", [{"name": choice.name, "value": choice.value} for choice in choices])

        body.put("data", data)
        await self._request(route, json=body, no_auth=True)

    def build_action_row(self) -> special_endpoints.ActionRowBuilder:
        return special_endpoints_impl.ActionRowBuilder()

    async def fetch_scheduled_event(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        event: snowflakes.SnowflakeishOr[scheduled_events.ScheduledEvent],
        /,
    ) -> scheduled_events.ScheduledEvent:
        route = routes.GET_GUILD_SCHEDULED_EVENT.compile(guild=guild, scheduled_event=event)
        query = data_binding.StringMapBuilder()
        query.put("with_user_count", True)

        response = await self._request(route, query=query)

        assert isinstance(response, dict)
        return self._entity_factory.deserialize_scheduled_event(response)

    async def fetch_scheduled_events(
        self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild], /
    ) -> typing.Sequence[scheduled_events.ScheduledEvent]:
        route = routes.GET_GUILD_SCHEDULED_EVENTS.compile(guild=guild)
        query = data_binding.StringMapBuilder()
        query.put("with_user_count", True)

        response = await self._request(route, query=query)

        assert isinstance(response, list)
        return [self._entity_factory.deserialize_scheduled_event(event) for event in response]

    async def _create_or_edit_scheduled_stage(
        self,
        route: routes.CompiledRoute,
        entity_type: undefined.UndefinedNoneOr[typing.Union[int, scheduled_events.ScheduledEventType]],
        name: undefined.UndefinedOr[str],
        *,
        channel: undefined.UndefinedNoneOr[snowflakes.SnowflakeishOr[channels_.PartialChannel]] = undefined.UNDEFINED,
        location: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        start_time: undefined.UndefinedOr[datetime.datetime] = undefined.UNDEFINED,
        description: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
        end_time: undefined.UndefinedNoneOr[datetime.datetime] = undefined.UNDEFINED,
        image: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        privacy_level: undefined.UndefinedOr[
            typing.Union[int, scheduled_events.EventPrivacyLevel]
        ] = undefined.UNDEFINED,
        status: undefined.UndefinedOr[typing.Union[int, scheduled_events.ScheduledEventStatus]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> data_binding.JSONObject:
        body = data_binding.JSONObjectBuilder()
        body.put_snowflake("channel_id", channel)
        body.put("name", name)
        body.put("privacy_level", privacy_level)
        body.put("scheduled_start_time", start_time, conversion=datetime.datetime.isoformat)
        body.put("scheduled_end_time", end_time, conversion=datetime.datetime.isoformat)
        body.put("description", description)
        body.put("entity_type", entity_type)
        body.put("status", status)

        if image is not undefined.UNDEFINED:
            image_resource = files.ensure_resource(image)
            async with image_resource.stream(executor=self._executor) as stream:
                body.put("image", await stream.data_uri())

        if location is not undefined.UNDEFINED:
            body["entity_metadata"] = {"location": location}

        response = await self._request(route, json=body, reason=reason)
        assert isinstance(response, dict)
        return response

    async def create_external_event(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        name: str,
        /,
        location: str,
        start_time: datetime.datetime,
        end_time: datetime.datetime,
        *,
        description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        image: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        privacy_level: typing.Union[
            int, scheduled_events.EventPrivacyLevel
        ] = scheduled_events.EventPrivacyLevel.GUILD_ONLY,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> scheduled_events.ScheduledExternalEvent:
        route = routes.POST_GUILD_SCHEDULED_EVENT.compile(guild=guild)
        response = await self._create_or_edit_scheduled_stage(
            route,
            scheduled_events.ScheduledEventType.EXTERNAL,
            name,
            location=location,
            start_time=start_time,
            description=description,
            end_time=end_time,
            image=image,
            privacy_level=privacy_level,
            reason=reason,
        )
        return self._entity_factory.deserialize_scheduled_external_event(response)

    async def create_stage_event(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        channel: snowflakes.SnowflakeishOr[channels_.PartialChannel],
        name: str,
        /,
        start_time: datetime.datetime,
        *,
        description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        end_time: undefined.UndefinedOr[datetime.datetime] = undefined.UNDEFINED,
        image: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        privacy_level: typing.Union[
            int, scheduled_events.EventPrivacyLevel
        ] = scheduled_events.EventPrivacyLevel.GUILD_ONLY,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> scheduled_events.ScheduledStageEvent:
        route = routes.POST_GUILD_SCHEDULED_EVENT.compile(guild=guild)
        response = await self._create_or_edit_scheduled_stage(
            route,
            scheduled_events.ScheduledEventType.STAGE_INSTANCE,
            name,
            channel=channel,
            start_time=start_time,
            description=description,
            end_time=end_time,
            image=image,
            privacy_level=privacy_level,
            reason=reason,
        )
        return self._entity_factory.deserialize_scheduled_stage_event(response)

    async def create_voice_event(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        channel: snowflakes.SnowflakeishOr[channels_.PartialChannel],
        name: str,
        /,
        start_time: datetime.datetime,
        *,
        description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        end_time: undefined.UndefinedOr[datetime.datetime] = undefined.UNDEFINED,
        image: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        privacy_level: typing.Union[
            int, scheduled_events.EventPrivacyLevel
        ] = scheduled_events.EventPrivacyLevel.GUILD_ONLY,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> scheduled_events.ScheduledVoiceEvent:
        route = routes.POST_GUILD_SCHEDULED_EVENT.compile(guild=guild)
        response = await self._create_or_edit_scheduled_stage(
            route,
            scheduled_events.ScheduledEventType.VOICE,
            name,
            channel=channel,
            start_time=start_time,
            description=description,
            end_time=end_time,
            image=image,
            privacy_level=privacy_level,
            reason=reason,
        )
        return self._entity_factory.deserialize_scheduled_voice_event(response)

    async def edit_scheduled_event(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        event: snowflakes.SnowflakeishOr[scheduled_events.ScheduledEvent],
        /,
        *,
        channel: undefined.UndefinedNoneOr[snowflakes.SnowflakeishOr[channels_.PartialChannel]] = undefined.UNDEFINED,
        description: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
        entity_type: undefined.UndefinedOr[
            typing.Union[int, scheduled_events.ScheduledEventType]
        ] = undefined.UNDEFINED,
        image: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
        location: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
        privacy_level: undefined.UndefinedOr[
            typing.Union[int, scheduled_events.EventPrivacyLevel]
        ] = undefined.UNDEFINED,
        start_time: undefined.UndefinedOr[datetime.datetime] = undefined.UNDEFINED,
        end_time: undefined.UndefinedNoneOr[datetime.datetime] = undefined.UNDEFINED,
        status: undefined.UndefinedOr[typing.Union[int, scheduled_events.ScheduledEventStatus]] = undefined.UNDEFINED,
        reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    ) -> scheduled_events.ScheduledEvent:
        route = routes.PATCH_GUILD_SCHEDULED_EVENT.compile(guild=guild, scheduled_event=event)

        if entity_type is not undefined.UNDEFINED:
            entity_type = scheduled_events.ScheduledEventType(entity_type)

            # Yes this does have to be explicitly set to None when changing to EXTERNAL
            if entity_type is scheduled_events.ScheduledEventType.EXTERNAL and channel is undefined.UNDEFINED:
                channel = None

        response = await self._create_or_edit_scheduled_stage(
            route,
            entity_type,
            name,
            channel=channel,
            start_time=start_time,
            description=description,
            end_time=end_time,
            image=image,
            location=location,
            privacy_level=privacy_level,
            status=status,
            reason=reason,
        )
        return self._entity_factory.deserialize_scheduled_event(response)

    async def delete_scheduled_event(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        event: snowflakes.SnowflakeishOr[scheduled_events.ScheduledEvent],
        /,
    ) -> None:
        route = routes.DELETE_GUILD_SCHEDULED_EVENT.compile(guild=guild, scheduled_event=event)

        await self._request(route)

    def fetch_scheduled_event_users(
        self,
        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
        event: snowflakes.SnowflakeishOr[scheduled_events.ScheduledEvent],
        /,
        *,
        newest_first: bool = False,
        start_at: undefined.UndefinedOr[snowflakes.SearchableSnowflakeishOr[users.PartialUser]] = undefined.UNDEFINED,
    ) -> iterators.LazyIterator[scheduled_events.ScheduledEventUser]:
        if start_at is undefined.UNDEFINED:
            start_at = snowflakes.Snowflake.max() if newest_first else snowflakes.Snowflake.min()
        elif isinstance(start_at, datetime.datetime):
            start_at = snowflakes.Snowflake.from_datetime(start_at)
        else:
            start_at = int(start_at)

        return special_endpoints_impl.ScheduledEventUserIterator(
            self._entity_factory, self._request, newest_first, str(start_at), guild, event
        )
Method resolution order
class RESTClientImpl
That's this class!
abstract class RESTClient

Interface for functionality that a REST API implementation provides.

trait NetworkSettingsAware

Structural supertype for any component aware of network settings.

trait FastProtocolChecking

An extension to make protocols with faster instance checks …

extern class Protocol

Base class for protocol classes …

extern class Generic

Abstract base class for generic types …

extern class abc.ABC

Helper class that provides a standard way to create an ABC using inheritance.

Variables and properties
property entity_factory : entity_factory_.EntityFactory

Entity factory used by this REST client.

property http_settingsHTTPSettings

Return the HTTP settings in use by this component.

Returns

hikari.config.HTTPSettings
The HTTP settings in use.
property is_alivebool

Whether this component is alive.

property proxy_settingsProxySettings

Return the proxy settings in use by this component.

Returns

hikari.config.ProxySettings
The proxy settings in use.
property token_type : Union[strTokenTypeNone]

Type of token this client is using for most requests.

Returns

Union[str, TokenType, None]

The type of token this client is using for most requests.

If this is None then this client will likely only work for some endpoints such as public and webhook ones.

Methods
async def add_reaction(
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    emoji: Union[stremojis.Emoji],
    emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = UNDEFINED,
) -> None: ...

Inherited from: RESTClient.add_reaction

Add a reaction emoji to a message in a given channel.

Parameters

channel : SnowflakeishOr[TextableChannel]
The channel where the message to add the reaction to is. This may be a TextableChannel or the ID of an existing channel.
message : SnowflakeishOr[PartialMessage]
The message to add a reaction to. This may be the object or the ID of an existing message.
emoji : Union[str, Emoji]
Object or name of the emoji to react with.

Other Parameters

emoji_id : UndefinedOr[SnowflakeishOr[CustomEmoji]]
ID of the custom emoji to react with. This should only be provided when a custom emoji's name is passed for emoji.

Raises

BadRequestError
If an invalid unicode emoji is given, or if the given custom emoji does not exist.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you are missing the ADD_REACTIONS (this is only necessary if you are the first person to add the reaction).
NotFoundError
If the channel or message is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def add_reaction(
    self,
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    emoji: typing.Union[str, emojis.Emoji],
    emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = undefined.UNDEFINED,
) -> None:
    route = routes.PUT_MY_REACTION.compile(
        emoji=self._transform_emoji_to_url_format(emoji, emoji_id),
        channel=channel,
        message=message,
    )
    await self._request(route)
async def add_role_to_member(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    user: snowflakes.SnowflakeishOr[users.PartialUser],
    role: snowflakes.SnowflakeishOr[guilds.PartialRole],
    *,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> None: ...

Inherited from: RESTClient.add_role_to_member

Add a role to a member.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild where the member is in. This may be the object or the ID of an existing guild.
user : SnowflakeishOr[PartialUser]
The user to add the role to. This may be the object or the ID of an existing user.
role : SnowflakeishOr[PartialRole]
The role to add. This may be the object or the ID of an existing role.

Other Parameters

reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Raises

ForbiddenError
If you are missing the MANAGE_ROLES permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the guild, user or role are not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def add_role_to_member(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    user: snowflakes.SnowflakeishOr[users.PartialUser],
    role: snowflakes.SnowflakeishOr[guilds.PartialRole],
    *,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> None:
    route = routes.PUT_GUILD_MEMBER_ROLE.compile(guild=guild, user=user, role=role)
    await self._request(route, reason=reason)
async def add_user_to_guild(
    access_token: Union[strapplications.PartialOAuth2Token],
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    user: snowflakes.SnowflakeishOr[users.PartialUser],
    *,
    nickname: undefined.UndefinedOr[str] = UNDEFINED,
    nick: undefined.UndefinedOr[str] = UNDEFINED,
    roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = UNDEFINED,
    mute: undefined.UndefinedOr[bool] = UNDEFINED,
    deaf: undefined.UndefinedOr[bool] = UNDEFINED,
) -> Optional[Member]: ...

Add a user to a guild.

Note

This requires the access_token to have the GUILDS_JOIN scope enabled along with the authorization of a Bot which has MANAGE_INVITES permission within the target guild.

Parameters

access_token : Union[str, PartialOAuth2Token]
Object or string of the access token to use for this request.
guild : SnowflakeishOr[PartialGuild]
The guild to add the user to. This may be the object or the ID of an existing guild.
user : SnowflakeishOr[PartialUser]
The user to add to the guild. This may be the object or the ID of an existing user.

Other Parameters

nickname : UndefinedOr[str]

If provided, the nick to add to the user when he joins the guild.

Requires the MANAGE_NICKNAMES permission on the guild.

nick : UndefinedNoneOr[str]

Deprecated alias for nickname.

Deprecated since version: 2.0.0.dev106

Use nickname instead.

roles : UndefinedOr[SnowflakeishSequence[PartialRole]]

If provided, the roles to add to the user when he joins the guild. This may be a collection objects or IDs of existing roles.

Requires the MANAGE_ROLES permission on the guild.

mute : UndefinedOr[bool]

If provided, the mute state to add the user when he joins the guild.

Requires the MUTE_MEMBERS permission on the guild.

deaf : UndefinedOr[bool]

If provided, the deaf state to add the user when he joins the guild.

Requires the DEAFEN_MEMBERS permission on the guild.

Returns

Optional[Member]
None if the user was already part of the guild, else Member.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
ForbiddenError
If you are not part of the guild you want to add the user to, if you are missing permissions to do one of the things you specified, if you are using an access token for another user, if the token is bound to another bot or if the access token doesn't have the GUILDS_JOIN scope enabled.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If you own the guild or the user is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def add_user_to_guild(
    self,
    access_token: typing.Union[str, applications.PartialOAuth2Token],
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    user: snowflakes.SnowflakeishOr[users.PartialUser],
    *,
    nickname: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    nick: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
    mute: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    deaf: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
) -> typing.Optional[guilds.Member]:
    """Add a user to a guild.

    !!! note
        This requires the `access_token` to have the
        `hikari.applications.OAuth2Scope.GUILDS_JOIN` scope enabled along
        with the authorization of a Bot which has `MANAGE_INVITES`
        permission within the target guild.

    Parameters
    ----------
    access_token : typing.Union[builtins.str, hikari.applications.PartialOAuth2Token]
        Object or string of the access token to use for this request.
    guild : hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]
        The guild to add the user to. This may be the object
        or the ID of an existing guild.
    user : hikari.snowflakes.SnowflakeishOr[hikari.users.PartialUser]
        The user to add to the guild. This may be the object
        or the ID of an existing user.

    Other Parameters
    ----------------
    nickname : hikari.undefined.UndefinedOr[builtins.str]
        If provided, the nick to add to the user when he joins the guild.

        Requires the `MANAGE_NICKNAMES` permission on the guild.
    nick : hikari.undefined.UndefinedNoneOr[builtins.str]
        Deprecated alias for `nickname`.

        .. deprecated:: 2.0.0.dev106
            Use `nickname` instead.
    roles : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishSequence[hikari.guilds.PartialRole]]
        If provided, the roles to add to the user when he joins the guild.
        This may be a collection objects or IDs of existing roles.

        Requires the `MANAGE_ROLES` permission on the guild.
    mute : hikari.undefined.UndefinedOr[builtins.bool]
        If provided, the mute state to add the user when he joins the guild.

        Requires the `MUTE_MEMBERS` permission on the guild.
    deaf : hikari.undefined.UndefinedOr[builtins.bool]
        If provided, the deaf state to add the user when he joins the guild.

        Requires the `DEAFEN_MEMBERS` permission on the guild.

    Returns
    -------
    typing.Optional[hikari.guilds.Member]
        `builtins.None` if the user was already part of the guild, else
        `hikari.guilds.Member`.

    Raises
    ------
    hikari.errors.BadRequestError
        If any of the fields that are passed have an invalid value.
    hikari.errors.ForbiddenError
        If you are not part of the guild you want to add the user to,
        if you are missing permissions to do one of the things you specified,
        if you are using an access token for another user, if the token is
        bound to another bot or if the access token doesn't have the
        `hikari.applications.OAuth2Scope.GUILDS_JOIN` scope enabled.
    hikari.errors.UnauthorizedError
        If you are unauthorized to make the request (invalid/missing token).
    hikari.errors.NotFoundError
        If you own the guild or the user is not found.
    hikari.errors.RateLimitTooLongError
        Raised in the event that a rate limit occurs that is
        longer than `max_rate_limit` when making a request.
    hikari.errors.RateLimitedError
        Usually, Hikari will handle and retry on hitting
        rate-limits automatically. This includes most bucket-specific
        rate-limits and global rate-limits. In some rare edge cases,
        however, Discord implements other undocumented rules for
        rate-limiting, such as limits per attribute. These cannot be
        detected or handled normally by Hikari due to their undocumented
        nature, and will trigger this exception if they occur.
    hikari.errors.InternalServerError
        If an internal error occurs on Discord while handling the request.
    """
    if nick is not undefined.UNDEFINED:
        deprecation.warn_deprecated(
            "nick",
            removal_version="2.0.0.dev113",
            additional_info="Use 'nickname' parameter instead",
        )
        nickname = nick

    route = routes.PUT_GUILD_MEMBER.compile(guild=guild, user=user)
    body = data_binding.JSONObjectBuilder()
    body.put("access_token", str(access_token))
    body.put("nick", nickname)
    body.put("mute", mute)
    body.put("deaf", deaf)
    body.put_snowflake_array("roles", roles)

    if (response := await self._request(route, json=body)) is not None:
        assert isinstance(response, dict)
        return self._entity_factory.deserialize_member(response, guild_id=snowflakes.Snowflake(guild))
    else:
        # User already is in the guild.
        return None
async def authorize_access_token(
    client: snowflakes.SnowflakeishOr[guilds.PartialApplication],
    client_secret: str,
    code: str,
    redirect_uri: str,
) -> OAuth2AuthorizationToken: ...

Inherited from: RESTClient.authorize_access_token

Authorize an OAuth2 token using the authorize code grant type.

Parameters

client : SnowflakeishOr[PartialApplication]
Object or ID of the application to authorize with.
client_secret : str
Secret of the application to authorize with.
code : str
The authorization code to exchange for an OAuth2 access token.
redirect_uri : str
The redirect uri that was included in the authorization request.

Returns

OAuth2AuthorizationToken
Object of the authorized OAuth2 token.

Raises

BadRequestError
If an invalid redirect uri or code is passed.
UnauthorizedError
When an client or client secret is passed.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def authorize_access_token(
    self,
    client: snowflakes.SnowflakeishOr[guilds.PartialApplication],
    client_secret: str,
    code: str,
    redirect_uri: str,
) -> applications.OAuth2AuthorizationToken:
    route = routes.POST_TOKEN.compile()
    form_builder = data_binding.URLEncodedFormBuilder()
    form_builder.add_field("grant_type", "authorization_code")
    form_builder.add_field("code", code)
    form_builder.add_field("redirect_uri", redirect_uri)

    response = await self._request(
        route, form_builder=form_builder, auth=self._gen_oauth2_token(client, client_secret)
    )
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_authorization_token(response)
async def authorize_client_credentials_token(
    client: snowflakes.SnowflakeishOr[guilds.PartialApplication],
    client_secret: str,
    scopes: Sequence[Union[applications.OAuth2Scopestr]],
) -> PartialOAuth2Token: ...

Inherited from: RESTClient.authorize_client_credentials_token

Authorize a client credentials token for an application.

Parameters

client : SnowflakeishOr[PartialApplication]
Object or ID of the application to authorize as.
client_secret : str
Secret of the application to authorize as.
scopes : Sequence[Union[OAuth2Scope, str]]
The scopes to authorize for.

Returns

PartialOAuth2Token
Object of the authorized partial OAuth2 token.

Raises

BadRequestError
If invalid any invalid or malformed scopes are passed.
UnauthorizedError
When an client or client secret is passed.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def authorize_client_credentials_token(
    self,
    client: snowflakes.SnowflakeishOr[guilds.PartialApplication],
    client_secret: str,
    scopes: typing.Sequence[typing.Union[applications.OAuth2Scope, str]],
) -> applications.PartialOAuth2Token:
    route = routes.POST_TOKEN.compile()
    form_builder = data_binding.URLEncodedFormBuilder()
    form_builder.add_field("grant_type", "client_credentials")
    form_builder.add_field("scope", " ".join(scopes))

    response = await self._request(
        route, form_builder=form_builder, auth=self._gen_oauth2_token(client, client_secret)
    )
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_partial_token(response)
def ban_member(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    user: snowflakes.SnowflakeishOr[users.PartialUser],
    *,
    delete_message_days: undefined.UndefinedOr[int] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> Coroutine[Any, Any, None]: ...

Inherited from: RESTClient.ban_member

Alias of RESTClient.ban_user.

Expand source code
Browse git
def ban_member(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    user: snowflakes.SnowflakeishOr[users.PartialUser],
    *,
    delete_message_days: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> typing.Coroutine[typing.Any, typing.Any, None]:
    return self.ban_user(guild, user, delete_message_days=delete_message_days, reason=reason)
async def ban_user(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    user: snowflakes.SnowflakeishOr[users.PartialUser],
    *,
    delete_message_days: undefined.UndefinedOr[int] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> None: ...

Inherited from: RESTClient.ban_user

Ban a member from a guild.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to ban the member from. This may be the object or the ID of an existing guild.
user : SnowflakeishOr[PartialUser]
The user to kick. This may be the object or the ID of an existing user.

Other Parameters

delete_message_days : UndefinedNoneOr[int]
If provided, the number of days to delete messages for. This must be between 0 and 7.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
ForbiddenError
If you are missing the BAN_MEMBERS permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the guild or user are not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def ban_user(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    user: snowflakes.SnowflakeishOr[users.PartialUser],
    *,
    delete_message_days: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> None:
    body = data_binding.JSONObjectBuilder()
    body.put("delete_message_days", delete_message_days)
    route = routes.PUT_GUILD_BAN.compile(guild=guild, user=user)
    await self._request(route, json=body, reason=reason)
async def begin_guild_prune(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    *,
    days: undefined.UndefinedOr[int] = UNDEFINED,
    compute_prune_count: undefined.UndefinedOr[bool] = UNDEFINED,
    include_roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> Optional[int]: ...

Inherited from: RESTClient.begin_guild_prune

Begin the guild prune.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to begin the guild prune in. This may be the object or the ID of an existing guild.

Other Parameters

days : UndefinedOr[int]
If provided, number of days to count prune for.
compute_prune_count : SnowflakeishOr[bool]
If provided, whether to return the prune count. This is discouraged for large guilds.
include_roles : UndefinedOr[SnowflakeishSequence[PartialRole]]
If provided, the role(s) to include. By default, this endpoint will not count users with roles. Providing roles using this attribute will make members with the specified roles also get included into the count.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

Optional[int]
If compute_prune_count is not provided or True, the number of members pruned. Else None.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you are missing the KICK_MEMBERS permission.
NotFoundError
If the guild is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def begin_guild_prune(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    *,
    days: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    compute_prune_count: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    include_roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> typing.Optional[int]:
    route = routes.POST_GUILD_PRUNE.compile(guild=guild)
    body = data_binding.JSONObjectBuilder()
    body.put("days", days)
    body.put("compute_prune_count", compute_prune_count)
    body.put_snowflake_array("include_roles", include_roles)
    response = await self._request(route, json=body, reason=reason)
    assert isinstance(response, dict)
    pruned = response.get("pruned")
    return int(pruned) if pruned is not None else None
def build_action_row() -> special_endpoints.ActionRowBuilder: ...

Inherited from: RESTClient.build_action_row

Build an action row message component for use in message create and REST calls.

Returns

ActionRowBuilder
The initialised action row builder.
Expand source code
Browse git
def build_action_row(self) -> special_endpoints.ActionRowBuilder:
    return special_endpoints_impl.ActionRowBuilder()
async def close() -> None: ...

Close the HTTP client and any open HTTP connections.

Expand source code
Browse git
@typing.final
async def close(self) -> None:
    """Close the HTTP client and any open HTTP connections."""
    live_attributes = self._get_live_attributes()
    self._live_attributes = None
    await live_attributes.close()
def command_builder(
    name: str,
    description: str,
) -> special_endpoints.SlashCommandBuilder: ...

Create a slash command builder to use in RESTClient.set_application_commands.

Deprecated since version: 2.0.0.dev106

Use RESTClient.slash_command_builder instead.

Parameters

name : str
The command's name. This should match the regex ^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$ in Unicode mode and be lowercase.
description : str
The description to set for the command. This should be inclusively between 1-100 characters in length.

Returns

SlashCommandBuilder
The created command builder object.
Expand source code
Browse git
def command_builder(self, name: str, description: str) -> special_endpoints.SlashCommandBuilder:
    r"""Create a slash command builder to use in `RESTClient.set_application_commands`.

    .. deprecated:: 2.0.0.dev106
        Use `RESTClient.slash_command_builder` instead.

    Parameters
    ----------
    name : builtins.str
        The command's name. This should match the regex `^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$` in
        Unicode mode and be lowercase.
    description : builtins.str
        The description to set for the command.
        This should be inclusively between 1-100 characters in length.

    Returns
    -------
    hikari.api.special_endpoints.SlashCommandBuilder
        The created command builder object.
    """
    deprecation.warn_deprecated(
        "command_builder",
        removal_version="2.0.0.dev113",
        additional_info="Use 'slash_command_builder' instead.",
    )
    return self.slash_command_builder(name, description)
def context_menu_command_builder(
    type: Union[commands.CommandTypeint],
    name: str,
) -> special_endpoints.ContextMenuCommandBuilder: ...

Inherited from: RESTClient.context_menu_command_builder

Create a command builder to use in RESTClient.set_application_commands.

Parameters

type : commands.CommandType
The commands's type.
name : str
The command's name.

Returns

ContextMenuCommandBuilder
The created command builder object.
Expand source code
Browse git
def context_menu_command_builder(
    self,
    type: typing.Union[commands.CommandType, int],
    name: str,
) -> special_endpoints.ContextMenuCommandBuilder:
    return special_endpoints_impl.ContextMenuCommandBuilder(commands.CommandType(type), name)
async def create_autocomplete_response(
    interaction: snowflakes.SnowflakeishOr[base_interactions.PartialInteraction],
    token: str,
    choices: Sequence[commands.CommandChoice],
) -> None: ...

Inherited from: RESTClient.create_autocomplete_response

Create the initial response for an autocomplete interaction.

Parameters

interaction : SnowflakeishOr[PartialInteraction]
Object or ID of the interaction this response is for.
token : str
The command interaction's token.

Other Parameters

choices : Sequence[commands.CommandChoice]
The autocomplete choices themselves.

Raises

UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the interaction is not found or if the interaction's initial response has already been created.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_autocomplete_response(
    self,
    interaction: snowflakes.SnowflakeishOr[base_interactions.PartialInteraction],
    token: str,
    choices: typing.Sequence[commands.CommandChoice],
) -> None:
    route = routes.POST_INTERACTION_RESPONSE.compile(interaction=interaction, token=token)

    body = data_binding.JSONObjectBuilder()
    body.put("type", base_interactions.ResponseType.AUTOCOMPLETE)

    data = data_binding.JSONObjectBuilder()
    data.put("choices", [{"name": choice.name, "value": choice.value} for choice in choices])

    body.put("data", data)
    await self._request(route, json=body, no_auth=True)
async def create_context_menu_command(
    application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
    type: Union[commands.CommandTypeint],
    name: str,
    *,
    guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = UNDEFINED,
    name_localizations: undefined.UndefinedOr[Mapping[Union[locales.Localestr], str]] = UNDEFINED,
    default_member_permissions: Union[undefined.UndefinedTypeintpermissions_.Permissions] = UNDEFINED,
    dm_enabled: undefined.UndefinedOr[bool] = UNDEFINED,
) -> ContextMenuCommand: ...

Inherited from: RESTClient.create_context_menu_command

Create an application command.

Parameters

application : SnowflakeishOr[PartialApplication]
Object or ID of the application to create a command for.
type : Union[CommandType, int]

The type of menu command to make.

Only USER and MESSAGE are valid here.

name : str
The command's name. This should match the regex ^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$ in Unicode mode and be lowercase.

Other Parameters

guild : UndefinedOr[SnowflakeishOr[PartialGuild]
Object or ID of the specific guild this should be made for. If left as UNDEFINED then this call will create a global command rather than a guild specific one.
name_localizations : UndefinedOr[Mapping[Union[Locale, str], str]]
The name localizations for this command.
default_member_permissions : Union[UndefinedType, int, Permissions]

Member permissions necessary to utilize this command by default.

If 0, then it will be available for all members. Note that this doesn't affect administrators of the guild and overwrites.

dm_enabled : UndefinedOr[bool]

Whether this command is enabled in DMs with the bot.

This can only be applied to non-guild commands.

Returns

ContextMenuCommand
Object of the created command.

Raises

ForbiddenError
If you cannot access the provided application's commands.
NotFoundError
If the provided application isn't found.
BadRequestError
If any of the fields that are passed have an invalid value.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_context_menu_command(
    self,
    application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
    type: typing.Union[commands.CommandType, int],
    name: str,
    *,
    guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    name_localizations: undefined.UndefinedOr[
        typing.Mapping[typing.Union[locales.Locale, str], str]
    ] = undefined.UNDEFINED,
    default_member_permissions: typing.Union[
        undefined.UndefinedType, int, permissions_.Permissions
    ] = undefined.UNDEFINED,
    dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
) -> commands.ContextMenuCommand:
    response = await self._create_application_command(
        application=application,
        type=type,
        name=name,
        guild=guild,
        name_localizations=name_localizations,
        default_member_permissions=default_member_permissions,
        dm_enabled=dm_enabled,
    )
    return self._entity_factory.deserialize_context_menu_command(
        response, guild_id=snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
    )
async def create_dm_channel(
    user: snowflakes.SnowflakeishOr[users.PartialUser],
    /,
) -> DMChannel: ...

Inherited from: RESTClient.create_dm_channel

Create a DM channel with a user.

Parameters

user : SnowflakeishOr[PartialUser]
The user to create the DM channel with. This may be the object or the ID of an existing user.

Returns

DMChannel
The created DM channel.

Raises

BadRequestError
If the user is not found.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_dm_channel(self, user: snowflakes.SnowflakeishOr[users.PartialUser], /) -> channels_.DMChannel:
    route = routes.POST_MY_CHANNELS.compile()
    body = data_binding.JSONObjectBuilder()
    body.put_snowflake("recipient_id", user)
    response = await self._request(route, json=body)
    assert isinstance(response, dict)
    channel = self._entity_factory.deserialize_dm(response)

    if self._cache:
        self._cache.set_dm_channel_id(user, channel.id)

    return channel
async def create_emoji(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    image: files.Resourceish,
    *,
    roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> KnownCustomEmoji: ...

Inherited from: RESTClient.create_emoji

Create an emoji in a guild.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to create the emoji on. This can be a guild object or the ID of an existing guild.
name : str
The name for the emoji.
image : Resourceish
The 128x128 image for the emoji. Maximum upload size is 256kb. This can be a still or an animated image.

Other Parameters

roles : UndefinedOr[SnowflakeishSequence[PartialRole]]
If provided, a collection of the roles that will be able to use this emoji. This can be a PartialRole or the ID of an existing role.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

KnownCustomEmoji
The created emoji.

Raises

BadRequestError
If any of the fields that are passed have an invalid value or if there are no more spaces for the type of emoji in the guild.
ForbiddenError
If you are missing MANAGE_EMOJIS_AND_STICKERS in the server.
NotFoundError
If the guild is not found.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_emoji(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    image: files.Resourceish,
    *,
    roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> emojis.KnownCustomEmoji:
    route = routes.POST_GUILD_EMOJIS.compile(guild=guild)
    body = data_binding.JSONObjectBuilder()
    body.put("name", name)
    image_resource = files.ensure_resource(image)
    async with image_resource.stream(executor=self._executor) as stream:
        body.put("image", await stream.data_uri())

    body.put_snowflake_array("roles", roles)

    response = await self._request(route, json=body, reason=reason)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_known_custom_emoji(response, guild_id=snowflakes.Snowflake(guild))
async def create_external_event(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    /,
    location: str,
    start_time: datetime.datetime,
    end_time: datetime.datetime,
    *,
    description: undefined.UndefinedOr[str] = UNDEFINED,
    image: undefined.UndefinedOr[files.Resourceish] = UNDEFINED,
    privacy_level: Union[intscheduled_events.EventPrivacyLevel] = <EventPrivacyLevel.GUILD_ONLY: 2>,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> ScheduledExternalEvent: ...

Inherited from: RESTClient.create_external_event

Create a scheduled external event.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to create the event in.
name : str
The name of the event.
location : str
The location the event.
start_time : datetime.datetime
When the event is scheduled to start.
end_time : datetime.datetime
When the event is scheduled to end.

Other Parameters

description : UndefinedOr[str]
The event's description.
image : UndefinedOr[Resourceish]
The event's display image.
privacy_level : UndefinedOr[EventPrivacyLevel]

The event's privacy level.

This effects who can view and subscribe to the event.

reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

ScheduledExternalEvent
The created scheduled external event.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you are missing the MANAGE_EVENTS permission.
NotFoundError
If the guild or event is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_external_event(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    /,
    location: str,
    start_time: datetime.datetime,
    end_time: datetime.datetime,
    *,
    description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    image: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
    privacy_level: typing.Union[
        int, scheduled_events.EventPrivacyLevel
    ] = scheduled_events.EventPrivacyLevel.GUILD_ONLY,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> scheduled_events.ScheduledExternalEvent:
    route = routes.POST_GUILD_SCHEDULED_EVENT.compile(guild=guild)
    response = await self._create_or_edit_scheduled_stage(
        route,
        scheduled_events.ScheduledEventType.EXTERNAL,
        name,
        location=location,
        start_time=start_time,
        description=description,
        end_time=end_time,
        image=image,
        privacy_level=privacy_level,
        reason=reason,
    )
    return self._entity_factory.deserialize_scheduled_external_event(response)
async def create_guild_category(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    *,
    position: undefined.UndefinedOr[int] = UNDEFINED,
    permission_overwrites: undefined.UndefinedOr[Sequence[channels_.PermissionOverwrite]] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> GuildCategory: ...

Inherited from: RESTClient.create_guild_category

Create a category in a guild.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to create the channel in. This may be the object or the ID of an existing guild.
name : str
The channels name. Must be between 2 and 1000 characters.

Other Parameters

position : UndefinedOr[int]
If provided, the position of the category.
permission_overwrites : UndefinedOr[Sequence[PermissionOverwrite]]
If provided, the permission overwrites for the category.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

GuildCategory
The created category.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
ForbiddenError
If you are missing the MANAGE_CHANNEL permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the guild is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_guild_category(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    *,
    position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    permission_overwrites: undefined.UndefinedOr[
        typing.Sequence[channels_.PermissionOverwrite]
    ] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> channels_.GuildCategory:
    response = await self._create_guild_channel(
        guild,
        name,
        channels_.ChannelType.GUILD_CATEGORY,
        position=position,
        permission_overwrites=permission_overwrites,
        reason=reason,
    )
    return self._entity_factory.deserialize_guild_category(response)
async def create_guild_from_template(
    template: Union[strtemplates.Template],
    name: str,
    *,
    icon: undefined.UndefinedOr[files.Resourceish] = UNDEFINED,
) -> guilds.RESTGuild: ...

Inherited from: RESTClient.create_guild_from_template

Make a guild from a template.

Parameters

template : Union[str, Template]
The object or string code of the template to create a guild based on.
name : str
The new guilds name.

Other Parameters

icon : UndefinedOr[Resourceish]
If provided, the guild icon to set. Must be a 1024x1024 image or can be an animated gif when the guild has the ANIMATED_ICON feature.

Returns

RESTGuild
Object of the created guild.

Note

This endpoint can only be used by bots in less than 10 guilds.

Raises

BadRequestError
If any of the fields that are passed have an invalid value or if you call this as a bot that's in more than 10 guilds.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_guild_from_template(
    self,
    template: typing.Union[str, templates.Template],
    name: str,
    *,
    icon: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
) -> guilds.RESTGuild:
    template = template if isinstance(template, str) else template.code
    route = routes.POST_TEMPLATE.compile(template=template)
    body = data_binding.JSONObjectBuilder()
    body.put("name", name)

    if icon is not undefined.UNDEFINED:
        icon_resource = files.ensure_resource(icon)
        async with icon_resource.stream(executor=self._executor) as stream:
            body.put("icon", await stream.data_uri())

    response = await self._request(route, json=body)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_rest_guild(response)
async def create_guild_news_channel(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    *,
    position: undefined.UndefinedOr[int] = UNDEFINED,
    topic: undefined.UndefinedOr[str] = UNDEFINED,
    nsfw: undefined.UndefinedOr[bool] = UNDEFINED,
    rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = UNDEFINED,
    permission_overwrites: undefined.UndefinedOr[Sequence[channels_.PermissionOverwrite]] = UNDEFINED,
    category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> GuildNewsChannel: ...

Inherited from: RESTClient.create_guild_news_channel

Create a news channel in a guild.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to create the channel in. This may be the object or the ID of an existing guild.
name : str
The channels name. Must be between 2 and 1000 characters.

Other Parameters

position : UndefinedOr[int]
If provided, the position of the channel (relative to the category, if any).
topic : UndefinedOr[str]
If provided, the channels topic. Maximum 1024 characters.
nsfw : UndefinedOr[bool]
If provided, whether to mark the channel as NSFW.
rate_limit_per_user : UndefinedOr[Intervalish]
If provided, the amount of seconds a user has to wait before being able to send another message in the channel. Maximum 21600 seconds.
permission_overwrites : UndefinedOr[Sequence[PermissionOverwrite]]
If provided, the permission overwrites for the channel.
category : UndefinedOr[SnowflakeishOr[GuildCategory]]
The category to create the channel under. This may be the object or the ID of an existing category.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

GuildNewsChannel
The created channel.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
ForbiddenError
If you are missing the MANAGE_CHANNEL permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the guild is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_guild_news_channel(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    *,
    position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    topic: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
    permission_overwrites: undefined.UndefinedOr[
        typing.Sequence[channels_.PermissionOverwrite]
    ] = undefined.UNDEFINED,
    category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> channels_.GuildNewsChannel:
    response = await self._create_guild_channel(
        guild,
        name,
        channels_.ChannelType.GUILD_NEWS,
        position=position,
        topic=topic,
        nsfw=nsfw,
        rate_limit_per_user=rate_limit_per_user,
        permission_overwrites=permission_overwrites,
        category=category,
        reason=reason,
    )
    return self._entity_factory.deserialize_guild_news_channel(response)
async def create_guild_stage_channel(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    *,
    position: undefined.UndefinedOr[int] = UNDEFINED,
    user_limit: undefined.UndefinedOr[int] = UNDEFINED,
    bitrate: undefined.UndefinedOr[int] = UNDEFINED,
    permission_overwrites: undefined.UndefinedOr[Sequence[channels_.PermissionOverwrite]] = UNDEFINED,
    region: undefined.UndefinedOr[Union[voices.VoiceRegionstr]] = UNDEFINED,
    category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> channels_.GuildStageChannel: ...

Inherited from: RESTClient.create_guild_stage_channel

Create a stage channel in a guild.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to create the channel in. This may be the object or the ID of an existing guild.
name : str
The channel's name. Must be between 2 and 1000 characters.

Other Parameters

position : UndefinedOr[int]
If provided, the position of the channel (relative to the category, if any).
user_limit : UndefinedOr[int]
If provided, the maximum users in the channel at once. Must be between 0 and 99 with 0 meaning no limit.
bitrate : UndefinedOr[int]
If provided, the bitrate for the channel. Must be between 8000 and 96000 or 8000 and 128000 for VIP servers.
permission_overwrites : UndefinedOr[Sequence[PermissionOverwrite]]
If provided, the permission overwrites for the channel.
region : UndefinedOr[Union[VoiceRegion, str]]
If provided, the voice region to for this channel. Passing None here will set it to "auto" mode where the used region will be decided based on the first person who connects to it when it's empty.
category : UndefinedOr[SnowflakeishOr[GuildCategory]]
The category to create the channel under. This may be the object or the ID of an existing category.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

GuildStageChannel
The created channel.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
ForbiddenError
If you are missing the MANAGE_CHANNEL permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the guild is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_guild_stage_channel(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    *,
    position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    permission_overwrites: undefined.UndefinedOr[
        typing.Sequence[channels_.PermissionOverwrite]
    ] = undefined.UNDEFINED,
    region: undefined.UndefinedOr[typing.Union[voices.VoiceRegion, str]] = undefined.UNDEFINED,
    category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> channels_.GuildStageChannel:
    response = await self._create_guild_channel(
        guild,
        name,
        channels_.ChannelType.GUILD_STAGE,
        position=position,
        user_limit=user_limit,
        bitrate=bitrate,
        permission_overwrites=permission_overwrites,
        region=region,
        category=category,
        reason=reason,
    )
    return self._entity_factory.deserialize_guild_stage_channel(response)
async def create_guild_text_channel(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    *,
    position: undefined.UndefinedOr[int] = UNDEFINED,
    topic: undefined.UndefinedOr[str] = UNDEFINED,
    nsfw: undefined.UndefinedOr[bool] = UNDEFINED,
    rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = UNDEFINED,
    permission_overwrites: undefined.UndefinedOr[Sequence[channels_.PermissionOverwrite]] = UNDEFINED,
    category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> GuildTextChannel: ...

Inherited from: RESTClient.create_guild_text_channel

Create a text channel in a guild.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to create the channel in. This may be the object or the ID of an existing guild.
name : str
The channels name. Must be between 2 and 1000 characters.

Other Parameters

position : UndefinedOr[int]
If provided, the position of the channel (relative to the category, if any).
topic : UndefinedOr[str]
If provided, the channels topic. Maximum 1024 characters.
nsfw : UndefinedOr[bool]
If provided, whether to mark the channel as NSFW.
rate_limit_per_user : UndefinedOr[Intervalish]
If provided, the amount of seconds a user has to wait before being able to send another message in the channel. Maximum 21600 seconds.
permission_overwrites : UndefinedOr[Sequence[PermissionOverwrite]]
If provided, the permission overwrites for the channel.
category : UndefinedOr[SnowflakeishOr[GuildCategory]]
The category to create the channel under. This may be the object or the ID of an existing category.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

GuildTextChannel
The created channel.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
ForbiddenError
If you are missing the MANAGE_CHANNEL permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the guild is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_guild_text_channel(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    *,
    position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    topic: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
    permission_overwrites: undefined.UndefinedOr[
        typing.Sequence[channels_.PermissionOverwrite]
    ] = undefined.UNDEFINED,
    category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> channels_.GuildTextChannel:
    response = await self._create_guild_channel(
        guild,
        name,
        channels_.ChannelType.GUILD_TEXT,
        position=position,
        topic=topic,
        nsfw=nsfw,
        rate_limit_per_user=rate_limit_per_user,
        permission_overwrites=permission_overwrites,
        category=category,
        reason=reason,
    )
    return self._entity_factory.deserialize_guild_text_channel(response)
async def create_guild_voice_channel(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    *,
    position: undefined.UndefinedOr[int] = UNDEFINED,
    user_limit: undefined.UndefinedOr[int] = UNDEFINED,
    bitrate: undefined.UndefinedOr[int] = UNDEFINED,
    video_quality_mode: undefined.UndefinedOr[Union[channels_.VideoQualityModeint]] = UNDEFINED,
    permission_overwrites: undefined.UndefinedOr[Sequence[channels_.PermissionOverwrite]] = UNDEFINED,
    region: undefined.UndefinedOr[Union[voices.VoiceRegionstr]] = UNDEFINED,
    category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> channels_.GuildVoiceChannel: ...

Inherited from: RESTClient.create_guild_voice_channel

Create a voice channel in a guild.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to create the channel in. This may be the object or the ID of an existing guild.
name : str
The channels name. Must be between 2 and 1000 characters.

Other Parameters

position : UndefinedOr[int]
If provided, the position of the channel (relative to the category, if any).
user_limit : UndefinedOr[int]
If provided, the maximum users in the channel at once. Must be between 0 and 99 with 0 meaning no limit.
bitrate : UndefinedOr[int]
If provided, the bitrate for the channel. Must be between 8000 and 96000 or 8000 and 128000 for VIP servers.
video_quality_mode : UndefinedOr[Union[VideoQualityMode, int]]
If provided, the new video quality mode for the channel.
permission_overwrites : UndefinedOr[Sequence[PermissionOverwrite]]
If provided, the permission overwrites for the channel.
region : UndefinedOr[Union[VoiceRegion, str]]
If provided, the voice region to for this channel. Passing None here will set it to "auto" mode where the used region will be decided based on the first person who connects to it when it's empty.
category : UndefinedOr[SnowflakeishOr[GuildCategory]]
The category to create the channel under. This may be the object or the ID of an existing category.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

GuildVoiceChannel
The created channel.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
ForbiddenError
If you are missing the MANAGE_CHANNEL permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the guild is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_guild_voice_channel(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    *,
    position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    video_quality_mode: undefined.UndefinedOr[typing.Union[channels_.VideoQualityMode, int]] = undefined.UNDEFINED,
    permission_overwrites: undefined.UndefinedOr[
        typing.Sequence[channels_.PermissionOverwrite]
    ] = undefined.UNDEFINED,
    region: undefined.UndefinedOr[typing.Union[voices.VoiceRegion, str]] = undefined.UNDEFINED,
    category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> channels_.GuildVoiceChannel:
    response = await self._create_guild_channel(
        guild,
        name,
        channels_.ChannelType.GUILD_VOICE,
        position=position,
        user_limit=user_limit,
        bitrate=bitrate,
        video_quality_mode=video_quality_mode,
        permission_overwrites=permission_overwrites,
        region=region,
        category=category,
        reason=reason,
    )
    return self._entity_factory.deserialize_guild_voice_channel(response)
async def create_interaction_response(
    interaction: snowflakes.SnowflakeishOr[base_interactions.PartialInteraction],
    token: str,
    response_type: Union[intbase_interactions.ResponseType],
    content: undefined.UndefinedNoneOr[Any] = UNDEFINED,
    *,
    flags: Union[intmessages_.MessageFlagundefined.UndefinedType] = UNDEFINED,
    tts: undefined.UndefinedOr[bool] = UNDEFINED,
    attachment: undefined.UndefinedOr[files.Resourceish] = UNDEFINED,
    attachments: undefined.UndefinedOr[Sequence[files.Resourceish]] = UNDEFINED,
    component: undefined.UndefinedOr[special_endpoints.ComponentBuilder] = UNDEFINED,
    components: undefined.UndefinedOr[Sequence[special_endpoints.ComponentBuilder]] = UNDEFINED,
    embed: undefined.UndefinedOr[embeds_.Embed] = UNDEFINED,
    embeds: undefined.UndefinedOr[Sequence[embeds_.Embed]] = UNDEFINED,
    replace_attachments: bool = False,
    mentions_everyone: undefined.UndefinedOr[bool] = UNDEFINED,
    user_mentions: undefined.UndefinedOr[Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]] = UNDEFINED,
    role_mentions: undefined.UndefinedOr[Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]] = UNDEFINED,
) -> None: ...

Inherited from: RESTClient.create_interaction_response

Create the initial response for a interaction.

Warning

Calling this with an interaction which already has an initial response will result in this raising a NotFoundError. This includes if the REST interaction server has already responded to the request.

Parameters

interaction : SnowflakeishOr[PartialInteraction]
Object or ID of the interaction this response is for.
token : str
The command interaction's token.
response_type : Union[int, ResponseType]
The type of interaction response this is.

Other Parameters

content : UndefinedOr[Any]

If provided, the message contents. If UNDEFINED, then nothing will be sent in the content. Any other value here will be cast to a str.

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

attachment : UndefinedOr[Resourceish],
If provided, the message attachment. This can be a resource, or string of a path on your computer or a URL.
attachments : UndefinedOr[Sequence[Resourceish]],
If provided, the message attachments. These can be resources, or strings consisting of paths on your computer or URLs.
component : UndefinedOr[ComponentBuilder]
If provided, builder object of the component to include in this message.
components : UndefinedOr[Sequence[ComponentBuilder]]
If provided, a sequence of the component builder objects to include in this message.
embed : UndefinedOr[Embed]
If provided, the message embed.
embeds : UndefinedOr[Sequence[Embed]]
If provided, the message embeds.
replace_attachments : bool

Whether to replace the attachments with the provided ones. Defaults to False. This only effects component interactions.

Note this will also overwrite the embed attachments.

flags : Union[int, MessageFlag, UndefinedType]

If provided, the message flags this response should have.

As of writing the only message flag which can be set here is EPHEMERAL.

tts : UndefinedOr[bool]
If provided, whether the message will be read out by a screen reader using Discord's TTS (text-to-speech) system.
mentions_everyone : UndefinedOr[bool]
If provided, whether the message should parse @everyone/@here mentions.
user_mentions : UndefinedOr[Union[SnowflakeishSequence[PartialUser], bool]]
If provided, and True, all user mentions will be detected. If provided, and False, all user mentions will be ignored if appearing in the message body. Alternatively this may be a collection of Snowflake, or PartialUser derivatives to enforce mentioning specific users.
role_mentions : UndefinedOr[Union[SnowflakeishSequence[PartialRole], bool]]
If provided, and True, all role mentions will be detected. If provided, and False, all role mentions will be ignored if appearing in the message body. Alternatively this may be a collection of Snowflake, or PartialRole derivatives to enforce mentioning specific roles.

Raises

ValueError
If more than 100 unique objects/entities are passed for role_mentions or user_mentions.
TypeError
If both embed and embeds are specified.
BadRequestError
This may be raised in several discrete situations, such as messages being empty with no embeds; messages with more than 2000 characters in them, embeds that exceed one of the many embed limits invalid image URLs in embeds.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the interaction is not found or if the interaction's initial response has already been created.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_interaction_response(
    self,
    interaction: snowflakes.SnowflakeishOr[base_interactions.PartialInteraction],
    token: str,
    response_type: typing.Union[int, base_interactions.ResponseType],
    content: undefined.UndefinedNoneOr[typing.Any] = undefined.UNDEFINED,
    *,
    flags: typing.Union[int, messages_.MessageFlag, undefined.UndefinedType] = undefined.UNDEFINED,
    tts: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
    attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
    component: undefined.UndefinedOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
    components: undefined.UndefinedOr[typing.Sequence[special_endpoints.ComponentBuilder]] = undefined.UNDEFINED,
    embed: undefined.UndefinedOr[embeds_.Embed] = undefined.UNDEFINED,
    embeds: undefined.UndefinedOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
    replace_attachments: bool = False,
    mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    user_mentions: undefined.UndefinedOr[
        typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
    ] = undefined.UNDEFINED,
    role_mentions: undefined.UndefinedOr[
        typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
    ] = undefined.UNDEFINED,
) -> None:
    route = routes.POST_INTERACTION_RESPONSE.compile(interaction=interaction, token=token)

    data, form = self._build_message_payload(
        content=content,
        attachment=attachment,
        attachments=attachments,
        component=component,
        components=components,
        embed=embed,
        embeds=embeds,
        replace_attachments=replace_attachments,
        tts=tts,
        flags=flags,
        mentions_everyone=mentions_everyone,
        user_mentions=user_mentions,
        role_mentions=role_mentions,
    )
    body = data_binding.JSONObjectBuilder()
    body.put("type", response_type)
    body.put("data", data)

    if form is not None:
        form.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
        await self._request(route, form_builder=form, no_auth=True)
    else:
        await self._request(route, json=body, no_auth=True)
async def create_invite(
    channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
    *,
    max_age: undefined.UndefinedOr[time.Intervalish] = UNDEFINED,
    max_uses: undefined.UndefinedOr[int] = UNDEFINED,
    temporary: undefined.UndefinedOr[bool] = UNDEFINED,
    unique: undefined.UndefinedOr[bool] = UNDEFINED,
    target_type: undefined.UndefinedOr[invites.TargetType] = UNDEFINED,
    target_user: undefined.UndefinedOr[snowflakes.SnowflakeishOr[users.PartialUser]] = UNDEFINED,
    target_application: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialApplication]] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> invites.InviteWithMetadata: ...

Inherited from: RESTClient.create_invite

Create an invite to the given guild channel.

Parameters

channel : SnowflakeishOr[GuildChannel]
The channel to create a invite for. This may be the object or the ID of an existing channel.

Other Parameters

max_age : UndefinedOr[Union[datetime.timedelta, float, int]]
If provided, the duration of the invite before expiry.
max_uses : UndefinedOr[int]
If provided, the max uses the invite can have.
temporary : UndefinedOr[bool]
If provided, whether the invite only grants temporary membership.
unique : UndefinedOr[bool]
If provided, whether the invite should be unique.
target_type : UndefinedOr[TargetType]
If provided, the target type of this invite.
target_user : UndefinedOr[SnowflakeishOr[PartialUser]]

If provided, the target user id for this invite. This may be the object or the ID of an existing user.

Note

This is required if target_type is STREAM and the targeted user must be streaming into the channel.

target_application : UndefinedOr[SnowflakeishOr[PartialApplication]]

If provided, the target application id for this invite. This may be the object or the ID of an existing application.

Note

This is required if target_type is EMBEDDED_APPLICATION and the targeted application must have the EMBEDDED flag.

reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

InviteWithMetadata
The invite to the given guild channel.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you are missing the MANAGE_CHANNELS permission.
NotFoundError
If the channel is not found, or if the target user does not exist, if provided.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_invite(
    self,
    channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
    *,
    max_age: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
    max_uses: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    temporary: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    unique: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    target_type: undefined.UndefinedOr[invites.TargetType] = undefined.UNDEFINED,
    target_user: undefined.UndefinedOr[snowflakes.SnowflakeishOr[users.PartialUser]] = undefined.UNDEFINED,
    target_application: undefined.UndefinedOr[
        snowflakes.SnowflakeishOr[guilds.PartialApplication]
    ] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> invites.InviteWithMetadata:
    route = routes.POST_CHANNEL_INVITES.compile(channel=channel)
    body = data_binding.JSONObjectBuilder()
    body.put("max_age", max_age, conversion=time.timespan_to_int)
    body.put("max_uses", max_uses)
    body.put("temporary", temporary)
    body.put("unique", unique)
    body.put("target_type", target_type)
    body.put_snowflake("target_user_id", target_user)
    body.put_snowflake("target_application_id", target_application)
    response = await self._request(route, json=body, reason=reason)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_invite_with_metadata(response)
async def create_message(
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    content: undefined.UndefinedOr[Any] = UNDEFINED,
    *,
    attachment: undefined.UndefinedOr[files.Resourceish] = UNDEFINED,
    attachments: undefined.UndefinedOr[Sequence[files.Resourceish]] = UNDEFINED,
    component: undefined.UndefinedOr[special_endpoints.ComponentBuilder] = UNDEFINED,
    components: undefined.UndefinedOr[Sequence[special_endpoints.ComponentBuilder]] = UNDEFINED,
    embed: undefined.UndefinedOr[embeds_.Embed] = UNDEFINED,
    embeds: undefined.UndefinedOr[Sequence[embeds_.Embed]] = UNDEFINED,
    tts: undefined.UndefinedOr[bool] = UNDEFINED,
    reply: undefined.UndefinedOr[snowflakes.SnowflakeishOr[messages_.PartialMessage]] = UNDEFINED,
    mentions_everyone: undefined.UndefinedOr[bool] = UNDEFINED,
    mentions_reply: undefined.UndefinedOr[bool] = UNDEFINED,
    user_mentions: undefined.UndefinedOr[Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]] = UNDEFINED,
    role_mentions: undefined.UndefinedOr[Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]] = UNDEFINED,
) -> messages_.Message: ...

Inherited from: RESTClient.create_message

Create a message in the given channel.

Parameters

channel : SnowflakeishOr[TextableChannel]
The channel to create the message in.
content : UndefinedOr[Any]

If provided, the message contents. If UNDEFINED, then nothing will be sent in the content. Any other value here will be cast to a str.

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

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

Other Parameters

attachment : UndefinedOr[Resourceish],
If provided, the message attachment. This can be a resource, or string of a path on your computer or a URL.
attachments : UndefinedOr[Sequence[Resourceish]],
If provided, the message attachments. These can be resources, or strings consisting of paths on your computer or URLs.
component : UndefinedOr[ComponentBuilder]
If provided, builder object of the component to include in this message.
components : UndefinedOr[Sequence[ComponentBuilder]]
If provided, a sequence of the component builder objects to include in this message.
embed : UndefinedOr[Embed]
If provided, the message embed.
embeds : UndefinedOr[Sequence[Embed]]
If provided, the message embeds.
tts : UndefinedOr[bool]
If provided, whether the message will be read out by a screen reader using Discord's TTS (text-to-speech) system.
reply : UndefinedOr[SnowflakeishOr[PartialMessage]]
If provided, the message to reply to.
mentions_everyone : UndefinedOr[bool]
If provided, whether the message should parse @everyone/@here mentions.
mentions_reply : UndefinedOr[bool]

If provided, whether to mention the author of the message that is being replied to.

This will not do anything if not being used with reply.

user_mentions : UndefinedOr[Union[SnowflakeishSequence[PartialUser], bool]]
If provided, and True, all user mentions will be detected. If provided, and False, all user mentions will be ignored if appearing in the message body. Alternatively this may be a collection of Snowflake, or PartialUser derivatives to enforce mentioning specific users.
role_mentions : UndefinedOr[Union[SnowflakeishSequence[PartialRole], bool]]
If provided, and True, all role mentions will be detected. If provided, and False, all role mentions will be ignored if appearing in the message body. Alternatively this may be a collection of Snowflake, or PartialRole derivatives to enforce mentioning specific roles.

Note

Attachments can be passed as many different things, to aid in convenience.

  • If a pathlib.PurePath or str to a valid URL, the resource at the given URL will be streamed to Discord when sending the message. Subclasses of WebResource such as URL, Attachment, Emoji, EmbedResource, etc will also be uploaded this way. This will use bit-inception, so only a small percentage of the resource will remain in memory at any one time, thus aiding in scalability.
  • If a Bytes is passed, or a str that contains a valid data URI is passed, then this is uploaded with a randomized file name if not provided.
  • If a File, pathlib.PurePath or str that is an absolute or relative path to a file on your file system is passed, then this resource is uploaded as an attachment using non-blocking code internally and streamed using bit-inception where possible. This depends on the type of concurrent.futures.Executor that is being used for the application (default is a thread pool which supports this behaviour).

Returns

Message
The created message.

Raises

ValueError
If more than 100 unique objects/entities are passed for role_mentions or user_mentions or if both attachment and attachments, component and components or embed and embeds are specified.
BadRequestError
This may be raised in several discrete situations, such as messages being empty with no attachments or embeds; messages with more than 2000 characters in them, embeds that exceed one of the many embed limits; too many attachments; attachments that are too large; invalid image URLs in embeds; if reply is not found or not in the same channel as channel; too many components.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you are missing the SEND_MESSAGES in the channel or the person you are trying to message has the DM's disabled.
NotFoundError
If the channel is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_message(
    self,
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    content: undefined.UndefinedOr[typing.Any] = undefined.UNDEFINED,
    *,
    attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
    attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
    component: undefined.UndefinedOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
    components: undefined.UndefinedOr[typing.Sequence[special_endpoints.ComponentBuilder]] = undefined.UNDEFINED,
    embed: undefined.UndefinedOr[embeds_.Embed] = undefined.UNDEFINED,
    embeds: undefined.UndefinedOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
    tts: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    reply: undefined.UndefinedOr[snowflakes.SnowflakeishOr[messages_.PartialMessage]] = undefined.UNDEFINED,
    mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    mentions_reply: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    user_mentions: undefined.UndefinedOr[
        typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
    ] = undefined.UNDEFINED,
    role_mentions: undefined.UndefinedOr[
        typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
    ] = undefined.UNDEFINED,
) -> messages_.Message:
    route = routes.POST_CHANNEL_MESSAGES.compile(channel=channel)
    body, form_builder = self._build_message_payload(
        content=content,
        attachment=attachment,
        attachments=attachments,
        component=component,
        components=components,
        embed=embed,
        embeds=embeds,
        tts=tts,
        mentions_everyone=mentions_everyone,
        mentions_reply=mentions_reply,
        user_mentions=user_mentions,
        role_mentions=role_mentions,
    )
    body.put("message_reference", reply, conversion=lambda m: {"message_id": str(int(m))})

    if form_builder is not None:
        form_builder.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
        response = await self._request(route, form_builder=form_builder)
    else:
        response = await self._request(route, json=body)

    assert isinstance(response, dict)
    return self._entity_factory.deserialize_message(response)
async def create_role(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    *,
    name: undefined.UndefinedOr[str] = UNDEFINED,
    permissions: undefined.UndefinedOr[permissions_.Permissions] = <Permissions.NONE: 0>,
    color: undefined.UndefinedOr[colors.Colorish] = UNDEFINED,
    colour: undefined.UndefinedOr[colors.Colorish] = UNDEFINED,
    hoist: undefined.UndefinedOr[bool] = UNDEFINED,
    icon: undefined.UndefinedOr[files.Resourceish] = UNDEFINED,
    unicode_emoji: undefined.UndefinedOr[str] = UNDEFINED,
    mentionable: undefined.UndefinedOr[bool] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> Role: ...

Inherited from: RESTClient.create_role

Create a role.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to create the role in. This may be the object or the ID of an existing guild.

Other Parameters

name : UndefinedOr[str]
If provided, the name for the role.
permissions : UndefinedOr[Permissions]
The permissions to give the role. This will default to setting NO roles if left to the default value. This is in contrast to default behaviour on Discord where some random permissions will be set by default.
color : UndefinedOr[Colorish]
If provided, the role's color.
colour : UndefinedOr[Colorish]
An alias for color.
hoist : UndefinedOr[bool]
If provided, whether to hoist the role.
icon : UndefinedOr[Resourceish]
If provided, the role icon. Must be a 64x64 image under 256kb.
unicode_emoji : UndefinedOr[str]
If provided, the standard emoji to set as the role icon.
mentionable : UndefinedOr[bool]
If provided, whether to make the role mentionable.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

Role
The created role.

Raises

TypeError
If both color and colour are specified or if both icon and unicode_emoji are specified.
BadRequestError
If any of the fields that are passed have an invalid value.
ForbiddenError
If you are missing the MANAGE_ROLES permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the guild is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_role(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    *,
    name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    permissions: undefined.UndefinedOr[permissions_.Permissions] = permissions_.Permissions.NONE,
    color: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
    colour: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
    hoist: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    icon: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
    unicode_emoji: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    mentionable: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> guilds.Role:
    if not undefined.any_undefined(color, colour):
        raise TypeError("Can not specify 'color' and 'colour' together.")

    if not undefined.any_undefined(icon, unicode_emoji):
        raise TypeError("Can not specify 'icon' and 'unicode_emoji' together.")

    route = routes.POST_GUILD_ROLES.compile(guild=guild)
    body = data_binding.JSONObjectBuilder()
    body.put("name", name)
    body.put("permissions", permissions)
    body.put("color", color, conversion=colors.Color.of)
    body.put("color", colour, conversion=colors.Color.of)
    body.put("hoist", hoist)
    body.put("unicode_emoji", unicode_emoji)
    body.put("mentionable", mentionable)

    if icon is not undefined.UNDEFINED:
        icon_resource = files.ensure_resource(icon)
        async with icon_resource.stream(executor=self._executor) as stream:
            body.put("icon", await stream.data_uri())

    response = await self._request(route, json=body, reason=reason)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_role(response, guild_id=snowflakes.Snowflake(guild))
async def create_slash_command(
    application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
    name: str,
    description: str,
    *,
    guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = UNDEFINED,
    options: undefined.UndefinedOr[Sequence[commands.CommandOption]] = UNDEFINED,
    name_localizations: undefined.UndefinedOr[Mapping[Union[locales.Localestr], str]] = UNDEFINED,
    description_localizations: undefined.UndefinedOr[Mapping[Union[locales.Localestr], str]] = UNDEFINED,
    default_member_permissions: Union[undefined.UndefinedTypeintpermissions_.Permissions] = UNDEFINED,
    dm_enabled: undefined.UndefinedOr[bool] = UNDEFINED,
) -> SlashCommand: ...

Inherited from: RESTClient.create_slash_command

Create an application command.

Parameters

application : SnowflakeishOr[PartialApplication]
Object or ID of the application to create a command for.
name : str
The command's name. This should match the regex ^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$ in Unicode mode and be lowercase.
description : str
The description to set for the command. This should be inclusively between 1-100 characters in length.

Other Parameters

guild : UndefinedOr[SnowflakeishOr[PartialGuild]
Object or ID of the specific guild this should be made for. If left as UNDEFINED then this call will create a global command rather than a guild specific one.
options : UndefinedOr[Sequence[CommandOption]]
A sequence of up to 10 options for this command.
name_localizations : UndefinedOr[Mapping[Union[Locale, str], str]]
The name localizations for this command.
description_localizations : UndefinedOr[Mapping[Union[Locale, str], str]]
The name localizations for this command.
default_member_permissions : Union[UndefinedType, int, Permissions]

Member permissions necessary to utilize this command by default.

If 0, then it will be available for all members. Note that this doesn't affect administrators of the guild and overwrites.

dm_enabled : UndefinedOr[bool]

Whether this command is enabled in DMs with the bot.

This can only be applied to non-guild commands.

Returns

SlashCommand
Object of the created command.

Raises

ForbiddenError
If you cannot access the provided application's commands.
NotFoundError
If the provided application isn't found.
BadRequestError
If any of the fields that are passed have an invalid value.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_slash_command(
    self,
    application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
    name: str,
    description: str,
    *,
    guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
    name_localizations: undefined.UndefinedOr[
        typing.Mapping[typing.Union[locales.Locale, str], str]
    ] = undefined.UNDEFINED,
    description_localizations: undefined.UndefinedOr[
        typing.Mapping[typing.Union[locales.Locale, str], str]
    ] = undefined.UNDEFINED,
    default_member_permissions: typing.Union[
        undefined.UndefinedType, int, permissions_.Permissions
    ] = undefined.UNDEFINED,
    dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
) -> commands.SlashCommand:
    response = await self._create_application_command(
        application=application,
        type=commands.CommandType.SLASH,
        name=name,
        description=description,
        guild=guild,
        options=options,
        name_localizations=name_localizations,
        description_localizations=description_localizations,
        default_member_permissions=default_member_permissions,
        dm_enabled=dm_enabled,
    )
    return self._entity_factory.deserialize_slash_command(
        response, guild_id=snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
    )
async def create_stage_event(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    channel: snowflakes.SnowflakeishOr[channels_.PartialChannel],
    name: str,
    /,
    start_time: datetime.datetime,
    *,
    description: undefined.UndefinedOr[str] = UNDEFINED,
    end_time: undefined.UndefinedOr[datetime.datetime] = UNDEFINED,
    image: undefined.UndefinedOr[files.Resourceish] = UNDEFINED,
    privacy_level: Union[intscheduled_events.EventPrivacyLevel] = <EventPrivacyLevel.GUILD_ONLY: 2>,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> ScheduledStageEvent: ...

Inherited from: RESTClient.create_stage_event

Create a scheduled stage event.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to create the event in.
channel : SnowflakeishOr[PartialChannel]
The stage channel to create the event in.
name : str
The name of the event.
start_time : datetime.datetime
When the event is scheduled to start.

Other Parameters

description : UndefinedOr[str]
The event's description.
end_time : UndefinedOr[datetime.datetime]
When the event should be scheduled to end.
image : UndefinedOr[Resourceish]
The event's display image.
privacy_level : UndefinedOr[EventPrivacyLevel]

The event's privacy level.

This effects who can view and subscribe to the event.

reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

ScheduledStageEvent
The created scheduled stage event.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError

If you are missing permissions to create the scheduled event.

You need the following permissions in the target stage channel: MANAGE_EVENTS, VIEW_CHANNEL and CONNECT.

NotFoundError
If the guild or event is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_stage_event(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    channel: snowflakes.SnowflakeishOr[channels_.PartialChannel],
    name: str,
    /,
    start_time: datetime.datetime,
    *,
    description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    end_time: undefined.UndefinedOr[datetime.datetime] = undefined.UNDEFINED,
    image: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
    privacy_level: typing.Union[
        int, scheduled_events.EventPrivacyLevel
    ] = scheduled_events.EventPrivacyLevel.GUILD_ONLY,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> scheduled_events.ScheduledStageEvent:
    route = routes.POST_GUILD_SCHEDULED_EVENT.compile(guild=guild)
    response = await self._create_or_edit_scheduled_stage(
        route,
        scheduled_events.ScheduledEventType.STAGE_INSTANCE,
        name,
        channel=channel,
        start_time=start_time,
        description=description,
        end_time=end_time,
        image=image,
        privacy_level=privacy_level,
        reason=reason,
    )
    return self._entity_factory.deserialize_scheduled_stage_event(response)
async def create_sticker(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    tag: str,
    image: files.Resourceish,
    *,
    description: undefined.UndefinedOr[str] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> stickers.GuildSticker: ...

Inherited from: RESTClient.create_sticker

Create a sticker in a guild.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to create the sticker on. This can be a guild object or the ID of an existing guild.
name : str
The name for the sticker.
tag : str
The tag for the sticker.
image : Resourceish

The 320x320 image for the sticker. Maximum upload size is 500kb. This can be a still or an animated PNG or a Lottie.

Note

Lottie support is only available for verified and partnered servers.

Other Parameters

description : UndefinedOr[str]
If provided, the description of the sticker.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

GuildSticker
The created sticker.

Raises

BadRequestError
If any of the fields that are passed have an invalid value or if there are no more spaces for the sticker in the guild.
ForbiddenError
If you are missing MANAGE_EMOJIS_AND_STICKERS in the server.
NotFoundError
If the guild is not found.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_sticker(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    tag: str,
    image: files.Resourceish,
    *,
    description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> stickers.GuildSticker:
    route = routes.POST_GUILD_STICKERS.compile(guild=guild)
    form = data_binding.URLEncodedFormBuilder(executor=self._executor)
    form.add_field("name", name)
    form.add_field("tags", tag)
    form.add_field("description", description or "")
    form.add_resource("file", files.ensure_resource(image))

    response = await self._request(route, form_builder=form, reason=reason)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_guild_sticker(response)
async def create_template(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    *,
    description: undefined.UndefinedNoneOr[str] = UNDEFINED,
) -> templates.Template: ...

Inherited from: RESTClient.create_template

Create a guild template.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to create a template from.
name : str
The name to use for the created template.

Other Parameters

description : UndefinedNoneOr[str]
The description to set for the template.

Returns

Template
The object of the created template.

Raises

ForbiddenError
If you are not part of the guild.
NotFoundError
If the guild is not found or you are missing the MANAGE_GUILD permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_template(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    name: str,
    *,
    description: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
) -> templates.Template:
    route = routes.POST_GUILD_TEMPLATES.compile(guild=guild)
    body = data_binding.JSONObjectBuilder()
    body.put("name", name)
    body.put("description", description)
    response = await self._request(route, json=body)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_template(response)
async def create_voice_event(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    channel: snowflakes.SnowflakeishOr[channels_.PartialChannel],
    name: str,
    /,
    start_time: datetime.datetime,
    *,
    description: undefined.UndefinedOr[str] = UNDEFINED,
    end_time: undefined.UndefinedOr[datetime.datetime] = UNDEFINED,
    image: undefined.UndefinedOr[files.Resourceish] = UNDEFINED,
    privacy_level: Union[intscheduled_events.EventPrivacyLevel] = <EventPrivacyLevel.GUILD_ONLY: 2>,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> ScheduledVoiceEvent: ...

Inherited from: RESTClient.create_voice_event

Create a scheduled voice event.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to create the event in.
channel : SnowflakeishOr[PartialChannel]
The voice channel to create the event in.
name : str
The name of the event.
start_time : datetime.datetime
When the event is scheduled to start.

Other Parameters

description : UndefinedOr[str]
The event's description.
end_time : UndefinedOr[datetime.datetime]
When the event should be scheduled to end.
image : UndefinedOr[Resourceish]
The event's display image.
privacy_level : UndefinedOr[EventPrivacyLevel]

The event's privacy level.

This effects who can view and subscribe to the event.

reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

ScheduledVoiceEvent
The created scheduled voice event.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError

If you are missing permissions to create the scheduled event.

You need the following permissions in the target voice channel: MANAGE_EVENTS, VIEW_CHANNEL and CONNECT.

NotFoundError
If the guild or event is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_voice_event(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    channel: snowflakes.SnowflakeishOr[channels_.PartialChannel],
    name: str,
    /,
    start_time: datetime.datetime,
    *,
    description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    end_time: undefined.UndefinedOr[datetime.datetime] = undefined.UNDEFINED,
    image: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
    privacy_level: typing.Union[
        int, scheduled_events.EventPrivacyLevel
    ] = scheduled_events.EventPrivacyLevel.GUILD_ONLY,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> scheduled_events.ScheduledVoiceEvent:
    route = routes.POST_GUILD_SCHEDULED_EVENT.compile(guild=guild)
    response = await self._create_or_edit_scheduled_stage(
        route,
        scheduled_events.ScheduledEventType.VOICE,
        name,
        channel=channel,
        start_time=start_time,
        description=description,
        end_time=end_time,
        image=image,
        privacy_level=privacy_level,
        reason=reason,
    )
    return self._entity_factory.deserialize_scheduled_voice_event(response)
async def create_webhook(
    channel: snowflakes.SnowflakeishOr[channels_.WebhookChannelT],
    name: str,
    *,
    avatar: undefined.UndefinedOr[files.Resourceish] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> webhooks.IncomingWebhook: ...

Inherited from: RESTClient.create_webhook

Create webhook in a channel.

Parameters

channel : SnowflakeishOr[WebhookChannelT]
The channel where the webhook will be created. This may be the object or the ID of an existing channel.
name : str
The name for the webhook. This cannot be clyde.

Other Parameters

avatar : Optional[Resourceish]
If provided, the avatar for the webhook.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

IncomingWebhook
The created webhook.

Raises

BadRequestError
If name doesn't follow the restrictions enforced by discord.
ForbiddenError
If you are missing the MANAGE_WEBHOOKS permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the channel is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def create_webhook(
    self,
    channel: snowflakes.SnowflakeishOr[channels_.WebhookChannelT],
    name: str,
    *,
    avatar: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> webhooks.IncomingWebhook:
    route = routes.POST_CHANNEL_WEBHOOKS.compile(channel=channel)
    body = data_binding.JSONObjectBuilder()
    body.put("name", name)

    if avatar is not undefined.UNDEFINED:
        avatar_resource = files.ensure_resource(avatar)
        async with avatar_resource.stream(executor=self._executor) as stream:
            body.put("avatar", await stream.data_uri())

    response = await self._request(route, json=body, reason=reason)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_incoming_webhook(response)
async def crosspost_message(
    channel: snowflakes.SnowflakeishOr[channels_.GuildNewsChannel],
    message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
) -> messages_.Message: ...

Inherited from: RESTClient.crosspost_message

Broadcast an announcement message.

Parameters

channel : SnowflakeishOr[GuildNewsChannel]
The object or ID of the news channel to crosspost a message in.
message : SnowflakeishOr[PartialMessage]
The object or ID of the message to crosspost.

Returns

Message
The message object that was crossposted.

Raises

BadRequestError
If you tried to crosspost a message that has already been broadcast.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you try to crosspost a message by the current user without the SEND_MESSAGES permission for the target news channel or try to crosspost a message by another user without both the SEND_MESSAGES and MANAGE_MESSAGES permissions for the target channel.
NotFoundError
If the channel or message is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def crosspost_message(
    self,
    channel: snowflakes.SnowflakeishOr[channels_.GuildNewsChannel],
    message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
) -> messages_.Message:
    route = routes.POST_CHANNEL_CROSSPOST.compile(channel=channel, message=message)

    response = await self._request(route)

    assert isinstance(response, dict)
    return self._entity_factory.deserialize_message(response)
async def delete_all_reactions(
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
) -> None: ...

Inherited from: RESTClient.delete_all_reactions

Delete all reactions from a message.

Parameters

channel : SnowflakeishOr[TextableChannel]
The channel where the message to delete all reactions from is. This may be the object or the ID of an existing channel.
message : SnowflakeishOr[PartialMessage]
The message to delete all reaction from. This may be the object or the ID of an existing message.

Raises

BadRequestError
If an invalid unicode emoji is given, or if the given custom emoji does not exist.
ForbiddenError
If you are missing the MANAGE_MESSAGES permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the channel or message is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_all_reactions(
    self,
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
) -> None:
    route = routes.DELETE_ALL_REACTIONS.compile(channel=channel, message=message)
    await self._request(route)
async def delete_all_reactions_for_emoji(
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    emoji: Union[stremojis.Emoji],
    emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = UNDEFINED,
) -> None: ...

Inherited from: RESTClient.delete_all_reactions_for_emoji

Delete all reactions for a single emoji on a given message.

Parameters

channel : SnowflakeishOr[TextableChannel]
The channel where the message to delete the reactions from is. This may be the object or the ID of an existing channel.
message : SnowflakeishOr[PartialMessage]
The message to delete a reactions from. This may be the object or the ID of an existing message.
emoji : Union[str, Emoji]
Object or name of the emoji to remove all the reactions for.

Other Parameters

emoji_id : UndefinedOr[SnowflakeishOr[CustomEmoji]]
ID of the custom emoji to remove all the reactions for. This should only be provided when a custom emoji's name is passed for emoji.

Raises

BadRequestError
If an invalid unicode emoji is given, or if the given custom emoji does not exist.
ForbiddenError
If you are missing the MANAGE_MESSAGES permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the channel or message is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_all_reactions_for_emoji(
    self,
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    emoji: typing.Union[str, emojis.Emoji],
    emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = undefined.UNDEFINED,
) -> None:
    route = routes.DELETE_REACTION_EMOJI.compile(
        emoji=self._transform_emoji_to_url_format(emoji, emoji_id),
        channel=channel,
        message=message,
    )
    await self._request(route)
async def delete_application_command(
    application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
    command: snowflakes.SnowflakeishOr[commands.PartialCommand],
    guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = UNDEFINED,
) -> None: ...

Inherited from: RESTClient.delete_application_command

Delete a registered application command.

Parameters

application : SnowflakeishOr[PartialApplication]
Object or ID of the application to delete a command for.
command : SnowflakeishOr[PartialCommand]
Object or ID of the command to delete.

Other Parameters

guild : UndefinedOr[SnowflakeishOr[PartialGuild]]
Object or ID of the guild to delete a command for if this is a guild specific command. Leave this as UNDEFINED to delete a global command.

Raises

ForbiddenError
If you cannot access the provided application's commands.
NotFoundError
If the provided application or command isn't found.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_application_command(
    self,
    application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
    command: snowflakes.SnowflakeishOr[commands.PartialCommand],
    guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
) -> None:
    if guild is undefined.UNDEFINED:
        route = routes.DELETE_APPLICATION_COMMAND.compile(application=application, command=command)

    else:
        route = routes.DELETE_APPLICATION_GUILD_COMMAND.compile(
            application=application, command=command, guild=guild
        )

    await self._request(route)
async def delete_channel(
    channel: snowflakes.SnowflakeishOr[channels_.PartialChannel],
) -> PartialChannel: ...

Inherited from: RESTClient.delete_channel

Delete a channel in a guild, or close a DM.

Parameters

channel : SnowflakeishOr[PartialChannel]
The channel to delete. This may be the object or the ID of an existing channel.

Returns

PartialChannel
Object of the channel that was deleted.

Raises

UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you are missing the MANAGE_CHANNEL permission in the channel.
NotFoundError
If the channel is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.

Note

For Public servers, the set 'Rules' or 'Guidelines' channels and the 'Public Server Updates' channel cannot be deleted.

Expand source code
Browse git
async def delete_channel(
    self, channel: snowflakes.SnowflakeishOr[channels_.PartialChannel]
) -> channels_.PartialChannel:
    route = routes.DELETE_CHANNEL.compile(channel=channel)
    response = await self._request(route)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_channel(response)
async def delete_emoji(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    emoji: snowflakes.SnowflakeishOr[emojis.CustomEmoji],
    *,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> None: ...

Inherited from: RESTClient.delete_emoji

Delete an emoji in a guild.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to delete the emoji on. This can be a guild object or the ID of an existing guild.
emoji : SnowflakeishOr[CustomEmoji]
The emoji to delete. This can be a CustomEmoji or the ID of an existing emoji.

Other Parameters

reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Raises

ForbiddenError
If you are missing MANAGE_EMOJIS_AND_STICKERS in the server.
NotFoundError
If the guild or the emoji are not found.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_emoji(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    emoji: snowflakes.SnowflakeishOr[emojis.CustomEmoji],
    *,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> None:
    route = routes.DELETE_GUILD_EMOJI.compile(guild=guild, emoji=emoji)
    await self._request(route, reason=reason)
async def delete_guild(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
) -> None: ...

Inherited from: RESTClient.delete_guild

Delete a guild.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to delete. This may be the object or the ID of an existing guild.

Raises

ForbiddenError
If you are not the owner of the guild.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If you own the guild or if you are not in it.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_guild(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> None:
    route = routes.DELETE_GUILD.compile(guild=guild)
    await self._request(route)
async def delete_interaction_response(
    application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
    token: str,
) -> None: ...

Inherited from: RESTClient.delete_interaction_response

Delete the initial response of an interaction.

Parameters

application : SnowflakeishOr[PartialApplication]
Object or ID of the application to delete a command response for.
token : str
The interaction's token.

Raises

UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the interaction or response is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_interaction_response(
    self, application: snowflakes.SnowflakeishOr[guilds.PartialApplication], token: str
) -> None:
    route = routes.DELETE_INTERACTION_RESPONSE.compile(webhook=application, token=token)
    await self._request(route, no_auth=True)
async def delete_invite(
    invite: Union[invites.InviteCodestr],
) -> invites.Invite: ...

Inherited from: RESTClient.delete_invite

Delete an existing invite.

Parameters

invite : Union[InviteCode, str]
The invite to delete. This may be an invite object or the code of an existing invite.

Returns

Invite
Object of the invite that was deleted.

Raises

ForbiddenError
If you are missing the MANAGE_GUILD permission in the guild the invite is from or if you are missing the MANAGE_CHANNELS permission in the channel the invite is from.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the invite is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_invite(self, invite: typing.Union[invites.InviteCode, str]) -> invites.Invite:
    route = routes.DELETE_INVITE.compile(invite_code=invite if isinstance(invite, str) else invite.code)
    response = await self._request(route)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_invite(response)
async def delete_message(
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
) -> None: ...

Inherited from: RESTClient.delete_message

Delete a given message in a given channel.

Parameters

channel : SnowflakeishOr[TextableChannel]
The channel to delete the message in. This may be the object or the ID of an existing channel.
message : SnowflakeishOr[PartialMessage]
The message to delete. This may be the object or the ID of an existing message.

Raises

UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you are missing the MANAGE_MESSAGES, and the message is not sent by you.
NotFoundError
If the channel or message is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_message(
    self,
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
) -> None:
    route = routes.DELETE_CHANNEL_MESSAGE.compile(channel=channel, message=message)
    await self._request(route)
async def delete_messages(
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    messages: Union[snowflakes.SnowflakeishOr[messages_.PartialMessage], snowflakes.SnowflakeishIterable[messages_.PartialMessage]],
    /,
    *other_messages: snowflakes.SnowflakeishOr[messages_.PartialMessage],
) -> None: ...

Inherited from: RESTClient.delete_messages

Bulk-delete messages from the channel.

Parameters

channel : SnowflakeishOr[TextableChannel]
The channel to bulk delete the messages in. This may be the object or the ID of an existing channel.
messages : Union[SnowflakeishOr[PartialMessage], SnowflakeishIterable[PartialMessage]]
Either the object/ID of an existing message to delete or an iterable of the objects and/or IDs of existing messages to delete.

Other Parameters

*other_messages : SnowflakeishOr[PartialMessage]
The objects and/or IDs of other existing messages to delete.

Note

This API endpoint will only be able to delete 100 messages at a time. For anything more than this, multiple requests will be executed one-after-the-other, since the rate limits for this endpoint do not favour more than one request per bucket.

If one message is left over from chunking per 100 messages, or only one message is passed to this coroutine function, then the logic is expected to defer to delete_message. The implication of this is that the delete_message endpoint is ratelimited by a different bucket with different usage rates.

Warning

This endpoint is not atomic. If an error occurs midway through a bulk delete, you will not be able to revert any changes made up to this point.

Warning

Specifying any messages more than 14 days old will cause the call to fail, potentially with partial completion.

Raises

BulkDeleteError
An error containing the messages successfully deleted, and the messages that were not removed. The BaseException.__cause__ of the exception will be the original error that terminated this process.
Expand source code
Browse git
async def delete_messages(
    self,
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    messages: typing.Union[
        snowflakes.SnowflakeishOr[messages_.PartialMessage],
        snowflakes.SnowflakeishIterable[messages_.PartialMessage],
    ],
    /,
    *other_messages: snowflakes.SnowflakeishOr[messages_.PartialMessage],
) -> None:
    route = routes.POST_DELETE_CHANNEL_MESSAGES_BULK.compile(channel=channel)

    pending: typing.List[snowflakes.SnowflakeishOr[messages_.PartialMessage]] = []
    deleted: typing.List[snowflakes.SnowflakeishOr[messages_.PartialMessage]] = []

    if isinstance(messages, typing.Iterable):  # Syntactic sugar. Allows to use iterables
        pending.extend(messages)

    else:
        pending.append(messages)

    # This maintains the order in-order to keep a predictable deletion order.
    pending.extend(other_messages)

    while pending:
        # Discord only allows 2-100 messages in the BULK_DELETE endpoint. Because of that,
        # if the user wants 101 messages deleted, we will post 100 messages in bulk delete
        # and then the last message in a normal delete.
        # Along with this, the bucket size for v6 and v7 seems to be a bit restrictive. As of
        # 30th July 2020, this endpoint returned the following headers when being ratelimited:
        #       x-ratelimit-bucket         b05c0d8c2ab83895085006a8eae073a3
        #       x-ratelimit-limit          1
        #       x-ratelimit-remaining      0
        #       x-ratelimit-reset          1596033974.096
        #       x-ratelimit-reset-after    3.000
        # This kind of defeats the point of asynchronously gathering any of these
        # in the first place really. To save clogging up the event loop
        # (albeit at a cost of maybe a couple-dozen milliseconds per call),
        # I am just gonna invoke these sequentially instead.
        try:
            if len(pending) == 1:
                message = pending[0]
                try:
                    await self.delete_message(channel, message)
                except errors.NotFoundError as exc:
                    # If the message is not found then this error should be suppressed
                    # to keep consistency with how the bulk delete endpoint functions.
                    if exc.code != 10008:  # Unknown Message
                        raise

                deleted.append(message)

            else:
                body = data_binding.JSONObjectBuilder()
                chunk = pending[:100]
                body.put_snowflake_array("messages", chunk)
                await self._request(route, json=body)
                deleted += chunk

            pending = pending[100:]
        except Exception as ex:
            raise errors.BulkDeleteError(deleted, pending) from ex
async def delete_my_reaction(
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    emoji: Union[stremojis.Emoji],
    emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = UNDEFINED,
) -> None: ...

Inherited from: RESTClient.delete_my_reaction

Delete a reaction that your application user created.

Parameters

channel : SnowflakeishOr[TextableChannel]
The channel where the message to delete the reaction from is. This may be the object or the ID of an existing channel.
message : SnowflakeishOr[PartialMessage]
The message to delete a reaction from. This may be the object or the ID of an existing message.
emoji : Union[str, Emoji]
Object or name of the emoji to remove your reaction for.

Other Parameters

emoji_id : UndefinedOr[SnowflakeishOr[CustomEmoji]]
ID of the custom emoji to remove your reaction for. This should only be provided when a custom emoji's name is passed for emoji.

Raises

BadRequestError
If an invalid unicode emoji is given, or if the given custom emoji does not exist.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the channel or message is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_my_reaction(
    self,
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    emoji: typing.Union[str, emojis.Emoji],
    emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = undefined.UNDEFINED,
) -> None:
    route = routes.DELETE_MY_REACTION.compile(
        emoji=self._transform_emoji_to_url_format(emoji, emoji_id),
        channel=channel,
        message=message,
    )
    await self._request(route)
async def delete_permission_overwrite(
    channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
    target: Union[channels_.PermissionOverwriteguilds.PartialRoleusers.PartialUsersnowflakes.Snowflakeish],
) -> None: ...

Inherited from: RESTClient.delete_permission_overwrite

Delete a custom permission for an entity in a given guild channel.

Parameters

channel : SnowflakeishOr[GuildChannel]
The channel to delete a permission overwrite in. This may be the object, or the ID of an existing channel.
target : Union[PartialUser, PartialRole, PermissionOverwrite, Snowflakeish]
The channel overwrite to delete.

Raises

UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you are missing the MANAGE_PERMISSIONS permission in the channel.
NotFoundError
If the channel is not found or the target is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_permission_overwrite(
    self,
    channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
    target: typing.Union[
        channels_.PermissionOverwrite, guilds.PartialRole, users.PartialUser, snowflakes.Snowflakeish
    ],
) -> None:
    route = routes.DELETE_CHANNEL_PERMISSIONS.compile(channel=channel, overwrite=target)
    await self._request(route)
async def delete_reaction(
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    user: snowflakes.SnowflakeishOr[users.PartialUser],
    emoji: Union[stremojis.Emoji],
    emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = UNDEFINED,
) -> None: ...

Inherited from: RESTClient.delete_reaction

Delete a reaction from a message.

If you are looking to delete your own applications reaction, use delete_my_reaction.

Parameters

channel : SnowflakeishOr[TextableChannel]
The channel where the message to delete the reaction from is. This may be the object or the ID of an existing channel.
message : SnowflakeishOr[PartialMessage]
The message to delete a reaction from. This may be the object or the ID of an existing message.
user : SnowflakeishOr[PartialUser]
Object or ID of the user to remove the reaction of.
emoji : Union[str, Emoji]
Object or name of the emoji to react with.

Other Parameters

emoji_id : UndefinedOr[SnowflakeishOr[CustomEmoji]]
ID of the custom emoji to react with. This should only be provided when a custom emoji's name is passed for emoji.

Raises

BadRequestError
If an invalid unicode emoji is given, or if the given custom emoji does not exist.
ForbiddenError
If you are missing the MANAGE_MESSAGES permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the channel or message is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_reaction(
    self,
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    user: snowflakes.SnowflakeishOr[users.PartialUser],
    emoji: typing.Union[str, emojis.Emoji],
    emoji_id: undefined.UndefinedOr[snowflakes.SnowflakeishOr[emojis.CustomEmoji]] = undefined.UNDEFINED,
) -> None:
    route = routes.DELETE_REACTION_USER.compile(
        emoji=self._transform_emoji_to_url_format(emoji, emoji_id),
        channel=channel,
        message=message,
        user=user,
    )
    await self._request(route)
async def delete_role(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    role: snowflakes.SnowflakeishOr[guilds.PartialRole],
) -> None: ...

Inherited from: RESTClient.delete_role

Delete a role.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to delete the role in. This may be the object or the ID of an existing guild.
role : SnowflakeishOr[PartialRole]
The role to delete. This may be the object or the ID of an existing role.

Raises

ForbiddenError
If you are missing the MANAGE_ROLES permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the guild or role are not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_role(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    role: snowflakes.SnowflakeishOr[guilds.PartialRole],
) -> None:
    route = routes.DELETE_GUILD_ROLE.compile(guild=guild, role=role)
    await self._request(route)
async def delete_scheduled_event(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    event: snowflakes.SnowflakeishOr[scheduled_events.ScheduledEvent],
    /,
) -> None: ...

Inherited from: RESTClient.delete_scheduled_event

Delete a scheduled event.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to delete the event from.
event : SnowflakeishOr[ScheduledEvent]
The scheduled event to delete.

Raises

UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you are missing the MANAGE_EVENTS permission.
NotFoundError
If the guild or event is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_scheduled_event(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    event: snowflakes.SnowflakeishOr[scheduled_events.ScheduledEvent],
    /,
) -> None:
    route = routes.DELETE_GUILD_SCHEDULED_EVENT.compile(guild=guild, scheduled_event=event)

    await self._request(route)
async def delete_sticker(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    sticker: snowflakes.SnowflakeishOr[stickers.PartialSticker],
    *,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> None: ...

Inherited from: RESTClient.delete_sticker

Delete a sticker in a guild.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to delete the sticker on. This can be a guild object or the ID of an existing guild.
sticker : SnowflakeishOr[PartialSticker]
The sticker to delete. This can be a sticker object or the ID of an existing sticker.

Other Parameters

reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Raises

ForbiddenError
If you are missing MANAGE_EMOJIS_AND_STICKERS in the server.
NotFoundError
If the guild or the sticker are not found.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_sticker(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    sticker: snowflakes.SnowflakeishOr[stickers.PartialSticker],
    *,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> None:
    route = routes.DELETE_GUILD_STICKER.compile(guild=guild, sticker=sticker)
    await self._request(route, reason=reason)
async def delete_template(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    template: Union[strtemplates.Template],
) -> templates.Template: ...

Inherited from: RESTClient.delete_template

Delete a guild template.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to delete a template in.
template : Union[str, Template]
Object or string code of the template to delete.

Returns

Template
The deleted template's object.

Raises

ForbiddenError
If you are not part of the guild.
NotFoundError
If the guild is not found or you are missing the MANAGE_GUILD permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_template(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    template: typing.Union[str, templates.Template],
) -> templates.Template:
    template = template if isinstance(template, str) else template.code
    route = routes.DELETE_GUILD_TEMPLATE.compile(guild=guild, template=template)
    response = await self._request(route)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_template(response)
async def delete_webhook(
    webhook: snowflakes.SnowflakeishOr[webhooks.PartialWebhook],
    *,
    token: undefined.UndefinedOr[str] = UNDEFINED,
) -> None: ...

Inherited from: RESTClient.delete_webhook

Delete a webhook.

Parameters

webhook : SnowflakeishOr[PartialWebhook]
The webhook to delete. This may be the object or the ID of an existing webhook.

Other Parameters

token : UndefinedOr[str]
If provided, the webhook token that will be used to delete the webhook instead of the token the client was initialized with.

Raises

ForbiddenError
If you are missing the MANAGE_WEBHOOKS permission when not using a token.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the webhook is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_webhook(
    self,
    webhook: snowflakes.SnowflakeishOr[webhooks.PartialWebhook],
    *,
    token: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> None:
    if token is undefined.UNDEFINED:
        route = routes.DELETE_WEBHOOK.compile(webhook=webhook)
        no_auth = False
    else:
        route = routes.DELETE_WEBHOOK_WITH_TOKEN.compile(webhook=webhook, token=token)
        no_auth = True

    await self._request(route, no_auth=no_auth)
async def delete_webhook_message(
    webhook: Union[webhooks.ExecutableWebhooksnowflakes.Snowflakeish],
    token: str,
    message: snowflakes.SnowflakeishOr[messages_.Message],
) -> None: ...

Inherited from: RESTClient.delete_webhook_message

Delete a given message in a given channel.

Parameters

webhook : Union[Snowflakeish, ExecutableWebhook]
The webhook to execute. This may be the object or the ID of an existing webhook.
token : str
The webhook token.
message : SnowflakeishOr[PartialMessage]
The message to delete. This may be the object or the ID of an existing message.

Raises

UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the webhook or the message are not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def delete_webhook_message(
    self,
    webhook: typing.Union[webhooks.ExecutableWebhook, snowflakes.Snowflakeish],
    token: str,
    message: snowflakes.SnowflakeishOr[messages_.Message],
) -> None:
    # int(ExecutableWebhook) isn't guaranteed to be valid nor the ID used to execute this entity as a webhook.
    webhook_id = webhook if isinstance(webhook, int) else webhook.webhook_id
    route = routes.DELETE_WEBHOOK_MESSAGE.compile(webhook=webhook_id, token=token, message=message)
    await self._request(route, no_auth=True)
async def edit_application_command(
    application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
    command: snowflakes.SnowflakeishOr[commands.PartialCommand],
    guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = UNDEFINED,
    *,
    name: undefined.UndefinedOr[str] = UNDEFINED,
    description: undefined.UndefinedOr[str] = UNDEFINED,
    options: undefined.UndefinedOr[Sequence[commands.CommandOption]] = UNDEFINED,
    default_member_permissions: Union[undefined.UndefinedTypeintpermissions_.Permissions] = UNDEFINED,
    dm_enabled: undefined.UndefinedOr[bool] = UNDEFINED,
) -> PartialCommand: ...

Inherited from: RESTClient.edit_application_command

Edit a registered application command.

Parameters

application : SnowflakeishOr[PartialApplication]
Object or ID of the application to edit a command for.
command : SnowflakeishOr[PartialCommand]
Object or ID of the command to modify.

Other Parameters

guild : UndefinedOr[SnowflakeishOr[PartialGuild]]
Object or ID of the guild to edit a command for if this is a guild specific command. Leave this as UNDEFINED to delete a global command.
name : UndefinedOr[str]
The name to set for the command. Leave as UNDEFINED to not change.
description : UndefinedOr[str]
The description to set for the command. Leave as UNDEFINED to not change.
options : UndefinedOr[Sequence[CommandOption]]
A sequence of up to 10 options to set for this command. Leave this as UNDEFINED to not change.
default_member_permissions : Union[UndefinedType, int, Permissions]

Member permissions necessary to utilize this command by default.

If 0, then it will be available for all members. Note that this doesn't affect administrators of the guild and overwrites.

dm_enabled : UndefinedOr[bool]

Whether this command is enabled in DMs with the bot.

This can only be applied to non-guild commands.

Returns

PartialCommand
The edited command object.

Raises

ForbiddenError
If you cannot access the provided application's commands.
NotFoundError
If the provided application or command isn't found.
BadRequestError
If any of the fields that are passed have an invalid value.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_application_command(
    self,
    application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
    command: snowflakes.SnowflakeishOr[commands.PartialCommand],
    guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
    *,
    name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
    default_member_permissions: typing.Union[
        undefined.UndefinedType, int, permissions_.Permissions
    ] = undefined.UNDEFINED,
    dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
) -> commands.PartialCommand:
    if guild is undefined.UNDEFINED:
        route = routes.PATCH_APPLICATION_COMMAND.compile(application=application, command=command)

    else:
        route = routes.PATCH_APPLICATION_GUILD_COMMAND.compile(
            application=application, command=command, guild=guild
        )

    body = data_binding.JSONObjectBuilder()
    body.put("name", name)
    body.put("description", description)
    body.put_array("options", options, conversion=self._entity_factory.serialize_command_option)
    # Discord has some funky behaviour around what 0 means. They consider it to be the same as ADMINISTRATOR,
    # but we consider it to be the same as None for developer sanity reasons
    body.put("default_member_permissions", None if default_member_permissions == 0 else default_member_permissions)
    body.put("dm_permission", dm_enabled)

    response = await self._request(route, json=body)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_command(
        response, guild_id=snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
    )
async def edit_channel(
    channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
    /,
    *,
    name: undefined.UndefinedOr[str] = UNDEFINED,
    position: undefined.UndefinedOr[int] = UNDEFINED,
    topic: undefined.UndefinedOr[str] = UNDEFINED,
    nsfw: undefined.UndefinedOr[bool] = UNDEFINED,
    bitrate: undefined.UndefinedOr[int] = UNDEFINED,
    video_quality_mode: undefined.UndefinedOr[Union[channels_.VideoQualityModeint]] = UNDEFINED,
    user_limit: undefined.UndefinedOr[int] = UNDEFINED,
    rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = UNDEFINED,
    region: undefined.UndefinedNoneOr[Union[voices.VoiceRegionstr]] = UNDEFINED,
    permission_overwrites: undefined.UndefinedOr[Sequence[channels_.PermissionOverwrite]] = UNDEFINED,
    parent_category: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildCategory]] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> channels_.PartialChannel: ...

Inherited from: RESTClient.edit_channel

Edit a channel.

Parameters

channel : SnowflakeishOr[GuildChannel]
The channel to edit. This may be the object or the ID of an existing channel.

Other Parameters

name : UndefinedOr[[str]
If provided, the new name for the channel.
position : UndefinedOr[[int]
If provided, the new position for the channel.
topic : UndefinedOr[str]
If provided, the new topic for the channel.
nsfw : UndefinedOr[bool]
If provided, whether the channel should be marked as NSFW or not.
bitrate : UndefinedOr[int]
If provided, the new bitrate for the channel.
video_quality_mode : UndefinedOr[Union[VideoQualityMode, int]]
If provided, the new video quality mode for the channel.
user_limit : UndefinedOr[int]
If provided, the new user limit in the channel.
rate_limit_per_user : UndefinedOr[Intervalish]
If provided, the new rate limit per user in the channel.
region : UndefinedOr[Union[str, VoiceRegion]]
If provided, the voice region to set for this channel. Passing None here will set it to "auto" mode where the used region will be decided based on the first person who connects to it when it's empty.
permission_overwrites : UndefinedOr[Sequence[PermissionOverwrite]]
If provided, the new permission overwrites for the channel.
parent_category : UndefinedOr[SnowflakeishOr[GuildCategory]]
If provided, the new guild category for the channel.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

PartialChannel
The edited channel.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you are missing permissions to edit the channel.
NotFoundError
If the channel is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_channel(
    self,
    channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
    /,
    *,
    name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    position: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    topic: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    nsfw: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    bitrate: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    video_quality_mode: undefined.UndefinedOr[typing.Union[channels_.VideoQualityMode, int]] = undefined.UNDEFINED,
    user_limit: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    rate_limit_per_user: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
    region: undefined.UndefinedNoneOr[typing.Union[voices.VoiceRegion, str]] = undefined.UNDEFINED,
    permission_overwrites: undefined.UndefinedOr[
        typing.Sequence[channels_.PermissionOverwrite]
    ] = undefined.UNDEFINED,
    parent_category: undefined.UndefinedOr[
        snowflakes.SnowflakeishOr[channels_.GuildCategory]
    ] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> channels_.PartialChannel:
    route = routes.PATCH_CHANNEL.compile(channel=channel)
    body = data_binding.JSONObjectBuilder()
    body.put("name", name)
    body.put("position", position)
    body.put("topic", topic)
    body.put("nsfw", nsfw)
    body.put("bitrate", bitrate)
    body.put("video_quality_mode", video_quality_mode)
    body.put("user_limit", user_limit)
    body.put("rate_limit_per_user", rate_limit_per_user, conversion=time.timespan_to_int)
    body.put("rtc_region", region, conversion=str)
    body.put_snowflake("parent_id", parent_category)
    body.put_array(
        "permission_overwrites",
        permission_overwrites,
        conversion=self._entity_factory.serialize_permission_overwrite,
    )

    response = await self._request(route, json=body, reason=reason)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_channel(response)
async def edit_emoji(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    emoji: snowflakes.SnowflakeishOr[emojis.CustomEmoji],
    *,
    name: undefined.UndefinedOr[str] = UNDEFINED,
    roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> KnownCustomEmoji: ...

Inherited from: RESTClient.edit_emoji

Edit an emoji in a guild.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to edit the emoji on. This can be a guild object or the ID of an existing guild.
emoji : SnowflakeishOr[CustomEmoji]
The emoji to edit. This can be a CustomEmoji or the ID of an existing emoji.

Other Parameters

name : UndefinedOr[str]
If provided, the new name for the emoji.
roles : UndefinedOr[SnowflakeishSequence[PartialRole]]
If provided, the new collection of roles that will be able to use this emoji. This can be a PartialRole or the ID of an existing role.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

KnownCustomEmoji
The edited emoji.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
ForbiddenError
If you are missing MANAGE_EMOJIS_AND_STICKERS in the server.
NotFoundError
If the guild or the emoji are not found.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_emoji(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    emoji: snowflakes.SnowflakeishOr[emojis.CustomEmoji],
    *,
    name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> emojis.KnownCustomEmoji:
    route = routes.PATCH_GUILD_EMOJI.compile(guild=guild, emoji=emoji)
    body = data_binding.JSONObjectBuilder()
    body.put("name", name)
    body.put_snowflake_array("roles", roles)

    response = await self._request(route, json=body, reason=reason)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_known_custom_emoji(response, guild_id=snowflakes.Snowflake(guild))
async def edit_guild(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    *,
    name: undefined.UndefinedOr[str] = UNDEFINED,
    verification_level: undefined.UndefinedOr[guilds.GuildVerificationLevel] = UNDEFINED,
    default_message_notifications: undefined.UndefinedOr[guilds.GuildMessageNotificationsLevel] = UNDEFINED,
    explicit_content_filter_level: undefined.UndefinedOr[guilds.GuildExplicitContentFilterLevel] = UNDEFINED,
    afk_channel: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.GuildVoiceChannel]] = UNDEFINED,
    afk_timeout: undefined.UndefinedOr[time.Intervalish] = UNDEFINED,
    icon: undefined.UndefinedNoneOr[files.Resourceish] = UNDEFINED,
    owner: undefined.UndefinedOr[snowflakes.SnowflakeishOr[users.PartialUser]] = UNDEFINED,
    splash: undefined.UndefinedNoneOr[files.Resourceish] = UNDEFINED,
    banner: undefined.UndefinedNoneOr[files.Resourceish] = UNDEFINED,
    system_channel: undefined.UndefinedNoneOr[snowflakes.SnowflakeishOr[channels_.GuildTextChannel]] = UNDEFINED,
    rules_channel: undefined.UndefinedNoneOr[snowflakes.SnowflakeishOr[channels_.GuildTextChannel]] = UNDEFINED,
    public_updates_channel: undefined.UndefinedNoneOr[snowflakes.SnowflakeishOr[channels_.GuildTextChannel]] = UNDEFINED,
    preferred_locale: undefined.UndefinedOr[Union[strlocales.Locale]] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> RESTGuild: ...

Inherited from: RESTClient.edit_guild

Edit a guild.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to edit. This may be the object or the ID of an existing guild.

Other Parameters

name : UndefinedOr[str]
If provided, the new name for the guild.
verification_level : UndefinedOr[GuildVerificationLevel]
If provided, the new verification level.
default_message_notifications : UndefinedOr[GuildMessageNotificationsLevel]
If provided, the new default message notifications level.
explicit_content_filter_level : UndefinedOr[GuildExplicitContentFilterLevel]
If provided, the new explicit content filter level.
afk_channel : UndefinedOr[SnowflakeishOr[GuildVoiceChannel]]
If provided, the new afk channel. Requires afk_timeout to be set to work.
afk_timeout : UndefinedOr[Intervalish]
If provided, the new afk timeout.
icon : UndefinedOr[Resourceish]
If provided, the new guild icon. Must be a 1024x1024 image or can be an animated gif when the guild has the ANIMATED_ICON feature.
owner : UndefinedOr[SnowflakeishOr[PartialUser]]]

If provided, the new guild owner.

Warning

You need to be the owner of the server to use this.

splash : UndefinedNoneOr[Resourceish]
If provided, the new guild splash. Must be a 16:9 image and the guild must have the INVITE_SPLASH feature.
banner : UndefinedNoneOr[Resourceish]
If provided, the new guild banner. Must be a 16:9 image and the guild must have the BANNER feature.
system_channel : UndefinedNoneOr[SnowflakeishOr[GuildTextChannel]]
If provided, the new system channel.
rules_channel : UndefinedNoneOr[SnowflakeishOr[GuildTextChannel]]
If provided, the new rules channel.
public_updates_channel : UndefinedNoneOr[SnowflakeishOr[GuildTextChannel]]
If provided, the new public updates channel.
preferred_locale : UndefinedNoneOr[str]
If provided, the new preferred locale.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

RESTGuild
The edited guild.

Raises

BadRequestError
If any of the fields that are passed have an invalid value. Or you are missing the
ForbiddenError
If you are missing the MANAGE_GUILD permission or if you tried to pass ownership without being the server owner.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the guild is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_guild(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    *,
    name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    verification_level: undefined.UndefinedOr[guilds.GuildVerificationLevel] = undefined.UNDEFINED,
    default_message_notifications: undefined.UndefinedOr[
        guilds.GuildMessageNotificationsLevel
    ] = undefined.UNDEFINED,
    explicit_content_filter_level: undefined.UndefinedOr[
        guilds.GuildExplicitContentFilterLevel
    ] = undefined.UNDEFINED,
    afk_channel: undefined.UndefinedOr[
        snowflakes.SnowflakeishOr[channels_.GuildVoiceChannel]
    ] = undefined.UNDEFINED,
    afk_timeout: undefined.UndefinedOr[time.Intervalish] = undefined.UNDEFINED,
    icon: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
    owner: undefined.UndefinedOr[snowflakes.SnowflakeishOr[users.PartialUser]] = undefined.UNDEFINED,
    splash: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
    banner: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
    system_channel: undefined.UndefinedNoneOr[
        snowflakes.SnowflakeishOr[channels_.GuildTextChannel]
    ] = undefined.UNDEFINED,
    rules_channel: undefined.UndefinedNoneOr[
        snowflakes.SnowflakeishOr[channels_.GuildTextChannel]
    ] = undefined.UNDEFINED,
    public_updates_channel: undefined.UndefinedNoneOr[
        snowflakes.SnowflakeishOr[channels_.GuildTextChannel]
    ] = undefined.UNDEFINED,
    preferred_locale: undefined.UndefinedOr[typing.Union[str, locales.Locale]] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> guilds.RESTGuild:
    route = routes.PATCH_GUILD.compile(guild=guild)
    body = data_binding.JSONObjectBuilder()
    body.put("name", name)
    body.put("verification_level", verification_level)
    body.put("default_message_notifications", default_message_notifications)
    body.put("explicit_content_filter", explicit_content_filter_level)
    body.put("afk_timeout", afk_timeout, conversion=time.timespan_to_int)
    body.put("preferred_locale", preferred_locale, conversion=str)
    body.put_snowflake("afk_channel_id", afk_channel)
    body.put_snowflake("owner_id", owner)
    body.put_snowflake("system_channel_id", system_channel)
    body.put_snowflake("rules_channel_id", rules_channel)
    body.put_snowflake("public_updates_channel_id", public_updates_channel)

    tasks: typing.List[asyncio.Task[str]] = []

    if icon is None:
        body.put("icon", None)
    elif icon is not undefined.UNDEFINED:
        icon_resource = files.ensure_resource(icon)
        async with icon_resource.stream(executor=self._executor) as stream:
            task = asyncio.create_task(stream.data_uri())
            task.add_done_callback(lambda future: body.put("icon", future.result()))
            tasks.append(task)

    if splash is None:
        body.put("splash", None)
    elif splash is not undefined.UNDEFINED:
        splash_resource = files.ensure_resource(splash)
        async with splash_resource.stream(executor=self._executor) as stream:
            task = asyncio.create_task(stream.data_uri())
            task.add_done_callback(lambda future: body.put("splash", future.result()))
            tasks.append(task)

    if banner is None:
        body.put("banner", None)
    elif banner is not undefined.UNDEFINED:
        banner_resource = files.ensure_resource(banner)
        async with banner_resource.stream(executor=self._executor) as stream:
            task = asyncio.create_task(stream.data_uri())
            task.add_done_callback(lambda future: body.put("banner", future.result()))
            tasks.append(task)

    await asyncio.gather(*tasks)

    response = await self._request(route, json=body, reason=reason)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_rest_guild(response)
async def edit_interaction_response(
    application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
    token: str,
    content: undefined.UndefinedNoneOr[Any] = UNDEFINED,
    *,
    attachment: undefined.UndefinedOr[files.Resourceish] = UNDEFINED,
    attachments: undefined.UndefinedOr[Sequence[files.Resourceish]] = UNDEFINED,
    component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = UNDEFINED,
    components: undefined.UndefinedNoneOr[Sequence[special_endpoints.ComponentBuilder]] = UNDEFINED,
    embed: undefined.UndefinedNoneOr[embeds_.Embed] = UNDEFINED,
    embeds: undefined.UndefinedNoneOr[Sequence[embeds_.Embed]] = UNDEFINED,
    replace_attachments: bool = False,
    mentions_everyone: undefined.UndefinedOr[bool] = UNDEFINED,
    user_mentions: undefined.UndefinedOr[Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]] = UNDEFINED,
    role_mentions: undefined.UndefinedOr[Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]] = UNDEFINED,
) -> messages_.Message: ...

Inherited from: RESTClient.edit_interaction_response

Edit the initial response to a command interaction.

Parameters

application : SnowflakeishOr[PartialApplication]
Object or ID of the application to edit a command response for.
token : str
The interaction's token.

Other Parameters

content : UndefinedOr[Any]

If provided, the message content to update with. If UNDEFINED, then the content will not be changed. If None, then the content will be removed.

Any other value will be cast to a str before sending.

If this is a Embed and neither the embed or embeds kwargs are provided or if this is a Resourceish and neither the attachment or attachments kwargs are provided, the values will be overwritten. This allows for simpler syntax when sending an embed or an attachment alone.

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

Whether to replace the attachments with the provided ones. Defaults to False.

Note this will also overwrite the embed attachments.

mentions_everyone : UndefinedOr[bool]
If provided, whether the message should parse @everyone/@here mentions.
user_mentions : UndefinedOr[Union[SnowflakeishSequence[PartialUser], bool]]
If provided, and True, all user mentions will be detected. If provided, and False, all user mentions will be ignored if appearing in the message body. Alternatively this may be a collection of Snowflake, or PartialUser derivatives to enforce mentioning specific users.
role_mentions : UndefinedOr[Union[SnowflakeishSequence[PartialRole], bool]]
If provided, and True, all role mentions will be detected. If provided, and False, all role mentions will be ignored if appearing in the message body. Alternatively this may be a collection of Snowflake, or PartialRole derivatives to enforce mentioning specific roles.

Note

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

Warning

If you specify one of mentions_everyone, user_mentions, or role_mentions, then all others will default to False, even if they were enabled previously.

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

Returns

Message
The edited message.

Raises

ValueError
If both attachment and attachments, component and components or embed and embeds are specified.
BadRequestError
This may be raised in several discrete situations, such as messages being empty with no attachments or embeds; messages with more than 2000 characters in them, embeds that exceed one of the many embed limits; too many attachments; attachments that are too large; invalid image URLs in embeds; too many components.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the interaction or the message are not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_interaction_response(
    self,
    application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
    token: str,
    content: undefined.UndefinedNoneOr[typing.Any] = undefined.UNDEFINED,
    *,
    attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
    attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
    component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
    components: undefined.UndefinedNoneOr[
        typing.Sequence[special_endpoints.ComponentBuilder]
    ] = undefined.UNDEFINED,
    embed: undefined.UndefinedNoneOr[embeds_.Embed] = undefined.UNDEFINED,
    embeds: undefined.UndefinedNoneOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
    replace_attachments: bool = False,
    mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    user_mentions: undefined.UndefinedOr[
        typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
    ] = undefined.UNDEFINED,
    role_mentions: undefined.UndefinedOr[
        typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
    ] = undefined.UNDEFINED,
) -> messages_.Message:
    route = routes.PATCH_INTERACTION_RESPONSE.compile(webhook=application, token=token)

    body, form_builder = self._build_message_payload(
        content=content,
        attachment=attachment,
        attachments=attachments,
        component=component,
        components=components,
        embed=embed,
        embeds=embeds,
        replace_attachments=replace_attachments,
        mentions_everyone=mentions_everyone,
        user_mentions=user_mentions,
        role_mentions=role_mentions,
        edit=True,
    )

    if form_builder is not None:
        form_builder.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
        response = await self._request(route, form_builder=form_builder, no_auth=True)
    else:
        response = await self._request(route, json=body, no_auth=True)

    assert isinstance(response, dict)
    return self._entity_factory.deserialize_message(response)
async def edit_member(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    user: snowflakes.SnowflakeishOr[users.PartialUser],
    *,
    nickname: undefined.UndefinedNoneOr[str] = UNDEFINED,
    nick: undefined.UndefinedNoneOr[str] = UNDEFINED,
    roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = UNDEFINED,
    mute: undefined.UndefinedOr[bool] = UNDEFINED,
    deaf: undefined.UndefinedOr[bool] = UNDEFINED,
    voice_channel: undefined.UndefinedNoneOr[snowflakes.SnowflakeishOr[channels_.GuildVoiceChannel]] = UNDEFINED,
    communication_disabled_until: undefined.UndefinedNoneOr[datetime.datetime] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> Member: ...

Edit a guild member.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to edit. This may be the object or the ID of an existing guild.
user : SnowflakeishOr[PartialGuild]
The guild to edit. This may be the object or the ID of an existing guild.

Other Parameters

nickname : UndefinedNoneOr[str]

If provided, the new nick for the member. If None, will remove the members nick.

Requires the MANAGE_NICKNAMES permission.

nick : UndefinedNoneOr[str]

Deprecated alias for nickname.

Deprecated since version: 2.0.0.dev104

Use nickname instead.

roles : UndefinedOr[SnowflakeishSequence[PartialRole]]

If provided, the new roles for the member.

Requires the MANAGE_ROLES permission.

mute : UndefinedOr[bool]

If provided, the new server mute state for the member.

Requires the MUTE_MEMBERS permission.

deaf : UndefinedOr[bool]

If provided, the new server deaf state for the member.

Requires the DEAFEN_MEMBERS permission.

voice_channel : UndefinedOr[SnowflakeishOr[GuildVoiceChannel]]]

If provided, None or the object or the ID of an existing voice channel to move the member to. If None, will disconnect the member from voice.

Requires the MOVE_MEMBERS permission and the CONNECT permission in the original voice channel and the target voice channel.

Note

If the member is not in a voice channel, this will take no effect.

communication_disabled_until : UndefinedNoneOr[datetime.datetime]

If provided, the datetime when the timeout (disable communication) of the member expires, up to 28 days in the future, or None to remove the timeout from the member.

Requires the MODERATE_MEMBERS permission.

reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

Member
Object of the member that was updated.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
ForbiddenError
If you are missing a permission to do an action.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the guild or the user are not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_member(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    user: snowflakes.SnowflakeishOr[users.PartialUser],
    *,
    nickname: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
    nick: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
    roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
    mute: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    deaf: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    voice_channel: undefined.UndefinedNoneOr[
        snowflakes.SnowflakeishOr[channels_.GuildVoiceChannel]
    ] = undefined.UNDEFINED,
    communication_disabled_until: undefined.UndefinedNoneOr[datetime.datetime] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> guilds.Member:
    """Edit a guild member.

    Parameters
    ----------
    guild : hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]
        The guild to edit. This may be the object
        or the ID of an existing guild.
    user : hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]
        The guild to edit. This may be the object
        or the ID of an existing guild.

    Other Parameters
    ----------------
    nickname : hikari.undefined.UndefinedNoneOr[builtins.str]
        If provided, the new nick for the member. If `builtins.None`,
        will remove the members nick.

        Requires the `MANAGE_NICKNAMES` permission.
    nick : hikari.undefined.UndefinedNoneOr[builtins.str]
        Deprecated alias for `nickname`.

        .. deprecated:: 2.0.0.dev104
            Use `nickname` instead.
    roles : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishSequence[hikari.guilds.PartialRole]]
        If provided, the new roles for the member.

        Requires the `MANAGE_ROLES` permission.
    mute : hikari.undefined.UndefinedOr[builtins.bool]
        If provided, the new server mute state for the member.

        Requires the `MUTE_MEMBERS` permission.
    deaf : hikari.undefined.UndefinedOr[builtins.bool]
        If provided, the new server deaf state for the member.

        Requires the `DEAFEN_MEMBERS` permission.
    voice_channel : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishOr[hikari.channels.GuildVoiceChannel]]]
        If provided, `builtins.None` or the object or the ID of
        an existing voice channel to move the member to.
        If `builtins.None`, will disconnect the member from voice.

        Requires the `MOVE_MEMBERS` permission and the `CONNECT`
        permission in the original voice channel and the target
        voice channel.

        !!! note
            If the member is not in a voice channel, this will
            take no effect.
    communication_disabled_until : hikari.undefined.UndefinedNoneOr[datetime.datetime]
        If provided, the datetime when the timeout (disable communication)
        of the member expires, up to 28 days in the future, or `builtins.None`
        to remove the timeout from the member.

        Requires the `MODERATE_MEMBERS` permission.
    reason : hikari.undefined.UndefinedOr[builtins.str]
        If provided, the reason that will be recorded in the audit logs.
        Maximum of 512 characters.

    Returns
    -------
    hikari.guilds.Member
        Object of the member that was updated.

    Raises
    ------
    hikari.errors.BadRequestError
        If any of the fields that are passed have an invalid value.
    hikari.errors.ForbiddenError
        If you are missing a permission to do an action.
    hikari.errors.UnauthorizedError
        If you are unauthorized to make the request (invalid/missing token).
    hikari.errors.NotFoundError
        If the guild or the user are not found.
    hikari.errors.RateLimitTooLongError
        Raised in the event that a rate limit occurs that is
        longer than `max_rate_limit` when making a request.
    hikari.errors.RateLimitedError
        Usually, Hikari will handle and retry on hitting
        rate-limits automatically. This includes most bucket-specific
        rate-limits and global rate-limits. In some rare edge cases,
        however, Discord implements other undocumented rules for
        rate-limiting, such as limits per attribute. These cannot be
        detected or handled normally by Hikari due to their undocumented
        nature, and will trigger this exception if they occur.
    hikari.errors.InternalServerError
        If an internal error occurs on Discord while handling the request.
    """
    if nick is not undefined.UNDEFINED:
        deprecation.warn_deprecated(
            "nick",
            removal_version="2.0.0.dev113",
            additional_info="Use 'nickname' parameter instead",
        )
        nickname = nick

    route = routes.PATCH_GUILD_MEMBER.compile(guild=guild, user=user)
    body = data_binding.JSONObjectBuilder()
    body.put("nick", nickname)
    body.put("mute", mute)
    body.put("deaf", deaf)
    body.put_snowflake_array("roles", roles)

    if voice_channel is None:
        body.put("channel_id", None)
    else:
        body.put_snowflake("channel_id", voice_channel)

    if isinstance(communication_disabled_until, datetime.datetime):
        body.put("communication_disabled_until", communication_disabled_until.isoformat())
    else:
        body.put("communication_disabled_until", communication_disabled_until)

    response = await self._request(route, json=body, reason=reason)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_member(response, guild_id=snowflakes.Snowflake(guild))
async def edit_message(
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    content: undefined.UndefinedOr[Any] = UNDEFINED,
    *,
    attachment: undefined.UndefinedOr[files.Resourceish] = UNDEFINED,
    attachments: undefined.UndefinedOr[Sequence[files.Resourceish]] = UNDEFINED,
    component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = UNDEFINED,
    components: undefined.UndefinedNoneOr[Sequence[special_endpoints.ComponentBuilder]] = UNDEFINED,
    embed: undefined.UndefinedNoneOr[embeds_.Embed] = UNDEFINED,
    embeds: undefined.UndefinedNoneOr[Sequence[embeds_.Embed]] = UNDEFINED,
    replace_attachments: bool = False,
    mentions_everyone: undefined.UndefinedOr[bool] = UNDEFINED,
    mentions_reply: undefined.UndefinedOr[bool] = UNDEFINED,
    user_mentions: undefined.UndefinedOr[Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]] = UNDEFINED,
    role_mentions: undefined.UndefinedOr[Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]] = UNDEFINED,
    flags: Union[undefined.UndefinedTypeintmessages_.MessageFlag] = UNDEFINED,
) -> messages_.Message: ...

Inherited from: RESTClient.edit_message

Edit an existing message in a given channel.

Parameters

channel : SnowflakeishOr[TextableChannel]
The channel to create the message in. This may be the object or the ID of an existing channel.
message : SnowflakeishOr[PartialMessage]
The message to edit. This may be the object or the ID of an existing message.
content : UndefinedOr[Any]

If provided, the message content to update with. If UNDEFINED, then the content will not be changed. If None, then the content will be removed.

Any other value will be cast to a str before sending.

If this is a Embed and neither the embed or embeds kwargs are provided or if this is a Resourceish and neither the attachment or attachments kwargs are provided, the values will be overwritten. This allows for simpler syntax when sending an embed or an attachment alone.

Other Parameters

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

Whether to replace the attachments with the provided ones. Defaults to False.

Note this will also overwrite the embed attachments.

mentions_everyone : UndefinedOr[bool]
If provided, sanitation for @everyone mentions. If UNDEFINED, then the previous setting is not changed. If True, then @everyone/@here mentions in the message content will show up as mentioning everyone that can view the chat.
mentions_reply : UndefinedOr[bool]

If provided, whether to mention the author of the message that is being replied to.

This will not do anything if message is not a reply message.

user_mentions : UndefinedOr[Union[SnowflakeishSequence[PartialUser], bool]]

If provided, sanitation for user mentions. If UNDEFINED, then the previous setting is not changed. If True, all valid user mentions will behave as mentions. If False, all valid user mentions will not behave as mentions.

You may alternatively pass a collection of Snowflake user IDs, or PartialUser-derived objects.

role_mentions : UndefinedOr[Union[SnowflakeishSequence[PartialRole], bool]]

If provided, sanitation for role mentions. If UNDEFINED, then the previous setting is not changed. If True, all valid role mentions will behave as mentions. If False, all valid role mentions will not behave as mentions.

You may alternatively pass a collection of Snowflake role IDs, or PartialRole-derived objects.

flags : UndefinedOr[MessageFlag]

If provided, optional flags to set on the message. If UNDEFINED, then nothing is changed.

Note that some flags may not be able to be set. Currently the only flags that can be set are NONE and SUPPRESS_EMBEDS. If you have MANAGE_MESSAGES permissions, you can use this call to suppress embeds on another user's message.

Note

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

Warning

If you specify a non-embed content, mentions_everyone, mentions_reply, user_mentions, and role_mentions will default to False as the message will be re-parsed for mentions.

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

Warning

If you specify one of mentions_everyone, mentions_reply, user_mentions, or role_mentions, then all others will default to False, even if they were enabled previously.

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

Warning

If the message was not sent by your user, the only parameter you may provide to this call is the flags parameter. Anything else will result in a ForbiddenError being raised.

Returns

Message
The edited message.

Raises

ValueError
If both attachment and attachments, component and components or embed and embeds are specified.
BadRequestError
This may be raised in several discrete situations, such as messages being empty with no embeds; messages with more than 2000 characters in them, embeds that exceed one of the many embed limits; invalid image URLs in embeds.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you are missing the SEND_MESSAGES in the channel; if you try to change the contents of another user's message; or if you try to edit the flags on another user's message without the MANAGE_MESSAGES permission.
NotFoundError
If the channel or message is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_message(
    self,
    channel: snowflakes.SnowflakeishOr[channels_.TextableChannel],
    message: snowflakes.SnowflakeishOr[messages_.PartialMessage],
    content: undefined.UndefinedOr[typing.Any] = undefined.UNDEFINED,
    *,
    attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
    attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
    component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
    components: undefined.UndefinedNoneOr[
        typing.Sequence[special_endpoints.ComponentBuilder]
    ] = undefined.UNDEFINED,
    embed: undefined.UndefinedNoneOr[embeds_.Embed] = undefined.UNDEFINED,
    embeds: undefined.UndefinedNoneOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
    replace_attachments: bool = False,
    mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    mentions_reply: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    user_mentions: undefined.UndefinedOr[
        typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
    ] = undefined.UNDEFINED,
    role_mentions: undefined.UndefinedOr[
        typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
    ] = undefined.UNDEFINED,
    flags: typing.Union[undefined.UndefinedType, int, messages_.MessageFlag] = undefined.UNDEFINED,
) -> messages_.Message:
    route = routes.PATCH_CHANNEL_MESSAGE.compile(channel=channel, message=message)
    body, form_builder = self._build_message_payload(
        content=content,
        attachment=attachment,
        attachments=attachments,
        component=component,
        components=components,
        embed=embed,
        embeds=embeds,
        replace_attachments=replace_attachments,
        flags=flags,
        mentions_everyone=mentions_everyone,
        mentions_reply=mentions_reply,
        user_mentions=user_mentions,
        role_mentions=role_mentions,
        edit=True,
    )

    if form_builder is not None:
        form_builder.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
        response = await self._request(route, form_builder=form_builder)
    else:
        response = await self._request(route, json=body)

    assert isinstance(response, dict)
    return self._entity_factory.deserialize_message(response)
async def edit_my_member(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    *,
    nickname: undefined.UndefinedNoneOr[str] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> Member: ...

Inherited from: RESTClient.edit_my_member

Edit the current user's member in a guild.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to edit the member in. This may be the object or the ID of an existing guild.

Other Parameters

nickname : UndefinedNoneOr[str]

If provided, the new nickname for the member. If None, will remove the members nickname.

Requires the CHANGE_NICKNAME permission. If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

Member
Object of the member that was updated.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
ForbiddenError
If you are missing a permission to do an action.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the guild is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_my_member(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    *,
    nickname: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> guilds.Member:
    route = routes.PATCH_MY_GUILD_MEMBER.compile(guild=guild)
    body = data_binding.JSONObjectBuilder()
    body.put("nick", nickname)

    response = await self._request(route, json=body, reason=reason)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_member(response, guild_id=snowflakes.Snowflake(guild))
async def edit_my_nick(
    guild: snowflakes.SnowflakeishOr[guilds.Guild],
    nick: Optional[str],
    *,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> None: ...

Edit the associated token's member nick.

Deprecated since version: 2.0.0.dev104

Use RESTClient.edit_my_member's nick argument instead.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to edit. This may be the object or the ID of an existing guild.
nick : Optional[str]
The new nick. If None, will remove the nick.

Other Parameters

reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Raises

ForbiddenError
If you are missing the CHANGE_NICKNAME permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the guild is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_my_nick(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.Guild],
    nick: typing.Optional[str],
    *,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> None:
    """Edit the associated token's member nick.

    .. deprecated:: 2.0.0.dev104
        Use `RESTClient.edit_my_member`'s `nick` argument instead.

    Parameters
    ----------
    guild : hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]
        The guild to edit. This may be the object
        or the ID of an existing guild.
    nick : typing.Optional[builtins.str]
        The new nick. If `builtins.None`,
        will remove the nick.

    Other Parameters
    ----------------
    reason : hikari.undefined.UndefinedOr[builtins.str]
        If provided, the reason that will be recorded in the audit logs.
        Maximum of 512 characters.

    Raises
    ------
    hikari.errors.ForbiddenError
        If you are missing the `CHANGE_NICKNAME` permission.
    hikari.errors.UnauthorizedError
        If you are unauthorized to make the request (invalid/missing token).
    hikari.errors.NotFoundError
        If the guild is not found.
    hikari.errors.RateLimitTooLongError
        Raised in the event that a rate limit occurs that is
        longer than `max_rate_limit` when making a request.
    hikari.errors.RateLimitedError
        Usually, Hikari will handle and retry on hitting
        rate-limits automatically. This includes most bucket-specific
        rate-limits and global rate-limits. In some rare edge cases,
        however, Discord implements other undocumented rules for
        rate-limiting, such as limits per attribute. These cannot be
        detected or handled normally by Hikari due to their undocumented
        nature, and will trigger this exception if they occur.
    hikari.errors.InternalServerError
        If an internal error occurs on Discord while handling the request.
    """
    deprecation.warn_deprecated(
        "edit_permission_overwrites",
        removal_version="2.0.0.dev113",
        additional_info="Use 'edit_my_member' with the nickname parameter instead.",
    )
    await self.edit_my_member(guild, nickname=nick, reason=reason)
async def edit_my_user(
    *,
    username: undefined.UndefinedOr[str] = UNDEFINED,
    avatar: undefined.UndefinedNoneOr[files.Resourceish] = UNDEFINED,
) -> OwnUser: ...

Inherited from: RESTClient.edit_my_user

Edit the token's associated user.

Other Parameters

username : undefined.UndefinedOr[str]
If provided, the new username.
avatar : undefined.UndefinedNoneOr[Resourceish]
If provided, the new avatar. If None, the avatar will be removed.

Returns

OwnUser
The edited token's associated user.

Raises

BadRequestError

If any of the fields that are passed have an invalid value.

Discord also returns this on a ratelimit: https://github.com/discord/discord-api-docs/issues/1462

UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_my_user(
    self,
    *,
    username: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    avatar: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
) -> users.OwnUser:
    route = routes.PATCH_MY_USER.compile()
    body = data_binding.JSONObjectBuilder()
    body.put("username", username)

    if avatar is None:
        body.put("avatar", None)
    elif avatar is not undefined.UNDEFINED:
        avatar_resource = files.ensure_resource(avatar)
        async with avatar_resource.stream(executor=self._executor) as stream:
            body.put("avatar", await stream.data_uri())

    response = await self._request(route, json=body)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_my_user(response)
async def edit_my_voice_state(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    channel: snowflakes.SnowflakeishOr[channels_.GuildStageChannel],
    *,
    suppress: undefined.UndefinedOr[bool] = UNDEFINED,
    request_to_speak: Union[undefined.UndefinedTypebooldatetime.datetime] = UNDEFINED,
) -> None: ...

Inherited from: RESTClient.edit_my_voice_state

Edit the current user's voice state in a stage channel.

Note

The current user has to have already joined the target stage channel before any calls can be made to this endpoint.

Parameters

guild : SnowflakeishOr[PartialGuild]
Object or Id of the guild to edit a voice state in.
channel : SnowflakeishOr[GuildStageChannel]
Object or Id of the channel to edit a voice state in.

Other Parameters

suppress : UndefinedOr[bool]
If specified, whether the user should be allowed to become a speaker in the target stage channel with builtin.True suppressing them from becoming one.
request_to_speak : Union[UndefinedType, bool, datetime.datetime]

Whether to request to speak. This may be one of the following:

  • True to indicate that the bot wants to speak.
  • False to remove any previously set request to speak.
  • datetime.datetime to specify when they want their request to speak timestamp to be set to.

Note

If a datetime from the past is passed then Discord will use the current time instead.

Raises

BadRequestError
If you try to target a non-staging channel.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you are missing the MUTE_MEMBERS permission in the channel.
NotFoundError
If the channel, message or voice state is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_my_voice_state(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    channel: snowflakes.SnowflakeishOr[channels_.GuildStageChannel],
    *,
    suppress: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    request_to_speak: typing.Union[undefined.UndefinedType, bool, datetime.datetime] = undefined.UNDEFINED,
) -> None:
    route = routes.PATCH_MY_GUILD_VOICE_STATE.compile(guild=guild)
    body = data_binding.JSONObjectBuilder()
    body.put_snowflake("channel_id", channel)
    body.put("suppress", suppress)

    if isinstance(request_to_speak, datetime.datetime):
        body.put("request_to_speak_timestamp", request_to_speak.isoformat())

    elif request_to_speak is True:
        body.put("request_to_speak_timestamp", time.utc_datetime().isoformat())

    elif request_to_speak is False:
        body.put("request_to_speak_timestamp", None)

    await self._request(route, json=body)
async def edit_permission_overwrite(
    channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
    target: Union[snowflakes.Snowflakeishusers.PartialUserguilds.PartialRolechannels_.PermissionOverwrite],
    *,
    target_type: undefined.UndefinedOr[Union[channels_.PermissionOverwriteTypeint]] = UNDEFINED,
    allow: undefined.UndefinedOr[permissions_.Permissions] = UNDEFINED,
    deny: undefined.UndefinedOr[permissions_.Permissions] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> None: ...

Inherited from: RESTClient.edit_permission_overwrite

Edit permissions for a specific entity in the given guild channel.

Parameters

channel : SnowflakeishOr[GuildChannel]
The channel to edit a permission overwrite in. This may be the object, or the ID of an existing channel.
target : Union[PartialUser, PartialRole, PermissionOverwrite, Snowflakeish]
The channel overwrite to edit. This may be the object or the ID of an existing overwrite.

Other Parameters

target_type : UndefinedOr[Union[PermissionOverwriteType, int]]
If provided, the type of the target to update. If unset, will attempt to get the type from target.
allow : UndefinedOr[Permissions]
If provided, the new value of all allowed permissions.
deny : UndefinedOr[Permissions]
If provided, the new value of all disallowed permissions.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Raises

TypeError
If target_type is unset and we were unable to determine the type from target.
BadRequestError
If any of the fields that are passed have an invalid value.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you are missing the MANAGE_PERMISSIONS permission in the channel.
NotFoundError
If the channel is not found or the target is not found if it is a role.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_permission_overwrite(
    self,
    channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
    target: typing.Union[
        snowflakes.Snowflakeish, users.PartialUser, guilds.PartialRole, channels_.PermissionOverwrite
    ],
    *,
    target_type: undefined.UndefinedOr[typing.Union[channels_.PermissionOverwriteType, int]] = undefined.UNDEFINED,
    allow: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
    deny: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> None:
    if target_type is undefined.UNDEFINED:
        if isinstance(target, users.PartialUser):
            target_type = channels_.PermissionOverwriteType.MEMBER
        elif isinstance(target, guilds.Role):
            target_type = channels_.PermissionOverwriteType.ROLE
        elif isinstance(target, channels_.PermissionOverwrite):
            target_type = target.type
        else:
            raise TypeError(
                "Cannot determine the type of the target to update. Try specifying 'target_type' manually."
            )

    target = target.id if isinstance(target, channels_.PermissionOverwrite) else target
    route = routes.PUT_CHANNEL_PERMISSIONS.compile(channel=channel, overwrite=target)
    body = data_binding.JSONObjectBuilder()
    body.put("type", target_type)
    body.put("allow", allow)
    body.put("deny", deny)
    await self._request(route, json=body, reason=reason)
async def edit_permission_overwrites(
    channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
    target: Union[snowflakes.Snowflakeishusers.PartialUserguilds.PartialRolechannels_.PermissionOverwrite],
    *,
    target_type: undefined.UndefinedOr[Union[channels_.PermissionOverwriteTypeint]] = UNDEFINED,
    allow: undefined.UndefinedOr[permissions_.Permissions] = UNDEFINED,
    deny: undefined.UndefinedOr[permissions_.Permissions] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> None: ...

Edit permissions for a specific entity in the given guild channel.

Deprecated since version: 2.0.0.dev110

Use RESTClient.edit_permission_overwrite instead.

Parameters

channel : SnowflakeishOr[GuildChannel]
The channel to edit a permission overwrite in. This may be the object, or the ID of an existing channel.
target : Union[PartialUser, PartialRole, PermissionOverwrite, Snowflakeish]
The channel overwrite to edit. This may be the object or the ID of an existing overwrite.

Other Parameters

target_type : UndefinedOr[Union[PermissionOverwriteType, int]]
If provided, the type of the target to update. If unset, will attempt to get the type from target.
allow : UndefinedOr[Permissions]
If provided, the new value of all allowed permissions.
deny : UndefinedOr[Permissions]
If provided, the new value of all disallowed permissions.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Raises

TypeError
If target_type is unset and we were unable to determine the type from target.
BadRequestError
If any of the fields that are passed have an invalid value.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you are missing the MANAGE_PERMISSIONS permission in the channel.
NotFoundError
If the channel is not found or the target is not found if it is a role.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_permission_overwrites(
    self,
    channel: snowflakes.SnowflakeishOr[channels_.GuildChannel],
    target: typing.Union[
        snowflakes.Snowflakeish, users.PartialUser, guilds.PartialRole, channels_.PermissionOverwrite
    ],
    *,
    target_type: undefined.UndefinedOr[typing.Union[channels_.PermissionOverwriteType, int]] = undefined.UNDEFINED,
    allow: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
    deny: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> None:
    """Edit permissions for a specific entity in the given guild channel.

    .. deprecated:: 2.0.0.dev110
        Use `RESTClient.edit_permission_overwrite` instead.

    Parameters
    ----------
    channel : hikari.snowflakes.SnowflakeishOr[hikari.channels.GuildChannel]
        The channel to edit a permission overwrite in. This may be the
        object, or the ID of an existing channel.
    target : typing.Union[hikari.users.PartialUser, hikari.guilds.PartialRole, hikari.channels.PermissionOverwrite, hikari.snowflakes.Snowflakeish]
        The channel overwrite to edit. This may be the object or the ID of an
        existing overwrite.

    Other Parameters
    ----------------
    target_type : hikari.undefined.UndefinedOr[typing.Union[hikari.channels.PermissionOverwriteType, int]]
        If provided, the type of the target to update. If unset, will attempt to get
        the type from `target`.
    allow : hikari.undefined.UndefinedOr[hikari.permissions.Permissions]
        If provided, the new value of all allowed permissions.
    deny : hikari.undefined.UndefinedOr[hikari.permissions.Permissions]
        If provided, the new value of all disallowed permissions.
    reason : hikari.undefined.UndefinedOr[builtins.str]
        If provided, the reason that will be recorded in the audit logs.
        Maximum of 512 characters.

    Raises
    ------
    builtins.TypeError
        If `target_type` is unset and we were unable to determine the type
        from `target`.
    hikari.errors.BadRequestError
        If any of the fields that are passed have an invalid value.
    hikari.errors.UnauthorizedError
        If you are unauthorized to make the request (invalid/missing token).
    hikari.errors.ForbiddenError
        If you are missing the `MANAGE_PERMISSIONS` permission in the channel.
    hikari.errors.NotFoundError
        If the channel is not found or the target is not found if it is
        a role.
    hikari.errors.RateLimitTooLongError
        Raised in the event that a rate limit occurs that is
        longer than `max_rate_limit` when making a request.
    hikari.errors.RateLimitedError
        Usually, Hikari will handle and retry on hitting
        rate-limits automatically. This includes most bucket-specific
        rate-limits and global rate-limits. In some rare edge cases,
        however, Discord implements other undocumented rules for
        rate-limiting, such as limits per attribute. These cannot be
        detected or handled normally by Hikari due to their undocumented
        nature, and will trigger this exception if they occur.
    hikari.errors.InternalServerError
        If an internal error occurs on Discord while handling the request.
    """  # noqa: E501 - Line too long
    deprecation.warn_deprecated(
        "edit_permission_overwrites",
        removal_version="2.0.0.dev113",
        additional_info="Use 'edit_permission_overwrite' instead",
    )
    await self.edit_permission_overwrite(
        channel, target, target_type=target_type, allow=allow, deny=deny, reason=reason
    )
async def edit_role(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    role: snowflakes.SnowflakeishOr[guilds.PartialRole],
    *,
    name: undefined.UndefinedOr[str] = UNDEFINED,
    permissions: undefined.UndefinedOr[permissions_.Permissions] = UNDEFINED,
    color: undefined.UndefinedOr[colors.Colorish] = UNDEFINED,
    colour: undefined.UndefinedOr[colors.Colorish] = UNDEFINED,
    hoist: undefined.UndefinedOr[bool] = UNDEFINED,
    icon: undefined.UndefinedNoneOr[files.Resourceish] = UNDEFINED,
    unicode_emoji: undefined.UndefinedNoneOr[str] = UNDEFINED,
    mentionable: undefined.UndefinedOr[bool] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> Role: ...

Inherited from: RESTClient.edit_role

Edit a role.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to edit the role in. This may be the object or the ID of an existing guild.
role : SnowflakeishOr[PartialRole]
The role to edit. This may be the object or the ID of an existing role.

Other Parameters

name : UndefinedOr[str]
If provided, the new name for the role.
permissions : UndefinedOr[Permissions]
If provided, the new permissions for the role.
color : UndefinedOr[Colorish]
If provided, the new color for the role.
colour : UndefinedOr[Colorish]
An alias for color.
hoist : UndefinedOr[bool]
If provided, whether to hoist the role.
icon : UndefinedNoneOr[Resourceish]
If provided, the new role icon. Must be a 64x64 image under 256kb.
unicode_emoji : UndefinedNoneOr[str]
If provided, the new unicode emoji to set as the role icon.
mentionable : UndefinedOr[bool]
If provided, whether to make the role mentionable.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

Role
The edited role.

Raises

TypeError
If both color and colour are specified or if both icon and unicode_emoji are specified.
BadRequestError
If any of the fields that are passed have an invalid value.
ForbiddenError
If you are missing the MANAGE_ROLES permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the guild or role are not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_role(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    role: snowflakes.SnowflakeishOr[guilds.PartialRole],
    *,
    name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    permissions: undefined.UndefinedOr[permissions_.Permissions] = undefined.UNDEFINED,
    color: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
    colour: undefined.UndefinedOr[colors.Colorish] = undefined.UNDEFINED,
    hoist: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    icon: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
    unicode_emoji: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
    mentionable: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> guilds.Role:
    if not undefined.any_undefined(color, colour):
        raise TypeError("Can not specify 'color' and 'colour' together.")

    if not undefined.any_undefined(icon, unicode_emoji):
        raise TypeError("Can not specify 'icon' and 'unicode_emoji' together.")

    route = routes.PATCH_GUILD_ROLE.compile(guild=guild, role=role)

    body = data_binding.JSONObjectBuilder()
    body.put("name", name)
    body.put("permissions", permissions)
    body.put("color", color, conversion=colors.Color.of)
    body.put("color", colour, conversion=colors.Color.of)
    body.put("hoist", hoist)
    body.put("unicode_emoji", unicode_emoji)
    body.put("mentionable", mentionable)

    if icon is None:
        body.put("icon", None)
    elif icon is not undefined.UNDEFINED:
        icon_resource = files.ensure_resource(icon)
        async with icon_resource.stream(executor=self._executor) as stream:
            body.put("icon", await stream.data_uri())

    response = await self._request(route, json=body, reason=reason)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_role(response, guild_id=snowflakes.Snowflake(guild))
async def edit_scheduled_event(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    event: snowflakes.SnowflakeishOr[scheduled_events.ScheduledEvent],
    /,
    *,
    channel: undefined.UndefinedNoneOr[snowflakes.SnowflakeishOr[channels_.PartialChannel]] = UNDEFINED,
    description: undefined.UndefinedNoneOr[str] = UNDEFINED,
    entity_type: undefined.UndefinedOr[Union[intscheduled_events.ScheduledEventType]] = UNDEFINED,
    image: undefined.UndefinedOr[files.Resourceish] = UNDEFINED,
    location: undefined.UndefinedOr[str] = UNDEFINED,
    name: undefined.UndefinedOr[str] = UNDEFINED,
    privacy_level: undefined.UndefinedOr[Union[intscheduled_events.EventPrivacyLevel]] = UNDEFINED,
    start_time: undefined.UndefinedOr[datetime.datetime] = UNDEFINED,
    end_time: undefined.UndefinedNoneOr[datetime.datetime] = UNDEFINED,
    status: undefined.UndefinedOr[Union[intscheduled_events.ScheduledEventStatus]] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> ScheduledEvent: ...

Inherited from: RESTClient.edit_scheduled_event

Edit a scheduled event.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to edit the event in.
event : SnowflakeishOr[ScheduledEvent]
The scheduled event to edit.

Other Parameters

channel : UndefinedNoneOr[SnowflakeishOr[PartialChannel]]
The channel a VOICE or STAGE event should be associated with.
description : UndefinedNoneOr[str]
The event's description.
entity_type : UndefinedOr[ScheduledEventType]
The type of entity the event should target.
image : UndefinedOr[Resourceish]
The event's display image.
location : UndefinedOr[str]

The location of an EXTERNAL event.

Must be passed when changing an event to EXTERNAL.

name : UndefinedOr[str]
The event's name.
privacy_level : UndefinedOr[EventPrivacyLevel]

The event's privacy level.

This effects who can view and subscribe to the event.

start_time : UndefinedOr[datetime.datetime]
When the event should be scheduled to start.
end_time : UndefinedNoneOr[datetime.datetime]

When the event should be scheduled to end.

This can only be set to None for STAGE and VOICE events. Must be provided when changing an event to EXTERNAL.

status : UndefinedOr[ScheduledEventStatus]

The event's new status.

SCHEDULED events can be set to ACTIVE and CANCELED. ACTIVE events can only be set to COMPLETED.

reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

ScheduledEvent
The edited scheduled event.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError

If you are missing permissions to edit the scheduled event.

For VOICE and STAGE_INSTANCE events, you need the following permissions in the event's associated channel: MANAGE_EVENTS, VIEW_CHANNEL and CONNECT.

For EXTERNAL events you just need the MANAGE_EVENTS permission.

NotFoundError
If the guild or event is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_scheduled_event(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    event: snowflakes.SnowflakeishOr[scheduled_events.ScheduledEvent],
    /,
    *,
    channel: undefined.UndefinedNoneOr[snowflakes.SnowflakeishOr[channels_.PartialChannel]] = undefined.UNDEFINED,
    description: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
    entity_type: undefined.UndefinedOr[
        typing.Union[int, scheduled_events.ScheduledEventType]
    ] = undefined.UNDEFINED,
    image: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
    location: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    privacy_level: undefined.UndefinedOr[
        typing.Union[int, scheduled_events.EventPrivacyLevel]
    ] = undefined.UNDEFINED,
    start_time: undefined.UndefinedOr[datetime.datetime] = undefined.UNDEFINED,
    end_time: undefined.UndefinedNoneOr[datetime.datetime] = undefined.UNDEFINED,
    status: undefined.UndefinedOr[typing.Union[int, scheduled_events.ScheduledEventStatus]] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> scheduled_events.ScheduledEvent:
    route = routes.PATCH_GUILD_SCHEDULED_EVENT.compile(guild=guild, scheduled_event=event)

    if entity_type is not undefined.UNDEFINED:
        entity_type = scheduled_events.ScheduledEventType(entity_type)

        # Yes this does have to be explicitly set to None when changing to EXTERNAL
        if entity_type is scheduled_events.ScheduledEventType.EXTERNAL and channel is undefined.UNDEFINED:
            channel = None

    response = await self._create_or_edit_scheduled_stage(
        route,
        entity_type,
        name,
        channel=channel,
        start_time=start_time,
        description=description,
        end_time=end_time,
        image=image,
        location=location,
        privacy_level=privacy_level,
        status=status,
        reason=reason,
    )
    return self._entity_factory.deserialize_scheduled_event(response)
async def edit_sticker(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    sticker: snowflakes.SnowflakeishOr[stickers.PartialSticker],
    *,
    name: undefined.UndefinedOr[str] = UNDEFINED,
    description: undefined.UndefinedOr[str] = UNDEFINED,
    tag: undefined.UndefinedOr[str] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> stickers.GuildSticker: ...

Inherited from: RESTClient.edit_sticker

Edit a sticker in a guild.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to edit the sticker on. This can be a guild object or the ID of an existing guild.
sticker : SnowflakeishOr[PartialSticker]
The sticker to edit. This can be a sticker object or the ID of an existing sticker.

Other Parameters

name : UndefinedOr[str]
If provided, the new name for the sticker.
description : UndefinedOr[str]
If provided, the new description for the sticker.
tag : UndefinedOr[str]
If provided, the new sticker tag.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

GuildSticker
The edited sticker.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
ForbiddenError
If you are missing MANAGE_EMOJIS_AND_STICKERS in the server.
NotFoundError
If the guild or the sticker are not found.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_sticker(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    sticker: snowflakes.SnowflakeishOr[stickers.PartialSticker],
    *,
    name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    tag: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> stickers.GuildSticker:
    route = routes.PATCH_GUILD_STICKER.compile(guild=guild, sticker=sticker)
    body = data_binding.JSONObjectBuilder()
    body.put("name", name)
    body.put("tags", tag)
    body.put("description", description)

    response = await self._request(route, json=body, reason=reason)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_guild_sticker(response)
async def edit_template(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    template: Union[strtemplates.Template],
    *,
    name: undefined.UndefinedOr[str] = UNDEFINED,
    description: undefined.UndefinedNoneOr[str] = UNDEFINED,
) -> templates.Template: ...

Inherited from: RESTClient.edit_template

Modify a guild template.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to edit a template in.
template : Union[str, Template]
Object or string code of the template to modify.

Other Parameters

name : UndefinedOr[str]
The name to set for this template.
description : UndefinedNoneOr[str]
The description to set for the template.

Returns

Template
The object of the edited template.

Raises

ForbiddenError
If you are not part of the guild.
NotFoundError
If the guild is not found or you are missing the MANAGE_GUILD permission.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_template(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    template: typing.Union[str, templates.Template],
    *,
    name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    description: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
) -> templates.Template:
    template = template if isinstance(template, str) else template.code
    route = routes.PATCH_GUILD_TEMPLATE.compile(guild=guild, template=template)
    body = data_binding.JSONObjectBuilder()
    body.put("name", name)
    body.put("description", description)

    response = await self._request(route, json=body)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_template(response)
async def edit_voice_state(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    channel: snowflakes.SnowflakeishOr[channels_.GuildStageChannel],
    user: snowflakes.SnowflakeishOr[users.PartialUser],
    *,
    suppress: undefined.UndefinedOr[bool] = UNDEFINED,
) -> None: ...

Inherited from: RESTClient.edit_voice_state

Edit an existing voice state in a stage channel.

Parameters

guild : SnowflakeishOr[PartialGuild]
Object or Id of the guild to edit a voice state in.
channel : SnowflakeishOr[GuildStageChannel]
Object or Id of the channel to edit a voice state in.
user : SnowflakeishOr[PartialUser]
Object or Id of the user to to edit the voice state of.

Other Parameters

suppress : UndefinedOr[bool]
If defined, whether the user should be allowed to become a speaker in the target stage channel.

Note

The target user must already be present in the stage channel before any calls are made to this endpoint.

Raises

BadRequestError
If you try to target a non-staging channel.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you are missing the MUTE_MEMBERS permission in the channel.
NotFoundError
If the channel, message or voice state is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_voice_state(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    channel: snowflakes.SnowflakeishOr[channels_.GuildStageChannel],
    user: snowflakes.SnowflakeishOr[users.PartialUser],
    *,
    suppress: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
) -> None:
    route = routes.PATCH_GUILD_VOICE_STATE.compile(guild=guild, user=user)
    body = data_binding.JSONObjectBuilder()
    body.put_snowflake("channel_id", channel)
    body.put("suppress", suppress)
    await self._request(route, json=body)
async def edit_webhook(
    webhook: snowflakes.SnowflakeishOr[webhooks.PartialWebhook],
    *,
    token: undefined.UndefinedOr[str] = UNDEFINED,
    name: undefined.UndefinedOr[str] = UNDEFINED,
    avatar: undefined.UndefinedNoneOr[files.Resourceish] = UNDEFINED,
    channel: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.WebhookChannelT]] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> webhooks.PartialWebhook: ...

Inherited from: RESTClient.edit_webhook

Edit a webhook.

Parameters

webhook : SnowflakeishOr[PartialWebhook]
The webhook to edit. This may be the object or the ID of an existing webhook.

Other Parameters

token : UndefinedOr[str]
If provided, the webhook token that will be used to edit the webhook instead of the token the client was initialized with.
name : UndefinedOr[str]
If provided, the new webhook name.
avatar : UndefinedNoneOr[Resourceish]
If provided, the new webhook avatar. If None, will remove the webhook avatar.
channel : UndefinedOr[SnowflakeishOr[WebhookChannelT]]
If provided, the text channel to move the webhook to.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

PartialWebhook
The edited webhook.

Raises

ForbiddenError
If you are missing the MANAGE_WEBHOOKS permission when not using a token.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the webhook is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_webhook(
    self,
    webhook: snowflakes.SnowflakeishOr[webhooks.PartialWebhook],
    *,
    token: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
    avatar: undefined.UndefinedNoneOr[files.Resourceish] = undefined.UNDEFINED,
    channel: undefined.UndefinedOr[snowflakes.SnowflakeishOr[channels_.WebhookChannelT]] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> webhooks.PartialWebhook:
    if token is undefined.UNDEFINED:
        route = routes.PATCH_WEBHOOK.compile(webhook=webhook)
        no_auth = False
    else:
        route = routes.PATCH_WEBHOOK_WITH_TOKEN.compile(webhook=webhook, token=token)
        no_auth = True

    body = data_binding.JSONObjectBuilder()
    body.put("name", name)
    body.put_snowflake("channel", channel)

    if avatar is None:
        body.put("avatar", None)
    elif avatar is not undefined.UNDEFINED:
        avatar_resource = files.ensure_resource(avatar)
        async with avatar_resource.stream(executor=self._executor) as stream:
            body.put("avatar", await stream.data_uri())

    response = await self._request(route, json=body, reason=reason, no_auth=no_auth)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_webhook(response)
async def edit_webhook_message(
    webhook: Union[webhooks.ExecutableWebhooksnowflakes.Snowflakeish],
    token: str,
    message: snowflakes.SnowflakeishOr[messages_.Message],
    content: undefined.UndefinedNoneOr[Any] = UNDEFINED,
    *,
    attachment: undefined.UndefinedOr[files.Resourceish] = UNDEFINED,
    attachments: undefined.UndefinedOr[Sequence[files.Resourceish]] = UNDEFINED,
    component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = UNDEFINED,
    components: undefined.UndefinedNoneOr[Sequence[special_endpoints.ComponentBuilder]] = UNDEFINED,
    embed: undefined.UndefinedNoneOr[embeds_.Embed] = UNDEFINED,
    embeds: undefined.UndefinedNoneOr[Sequence[embeds_.Embed]] = UNDEFINED,
    replace_attachments: bool = False,
    mentions_everyone: undefined.UndefinedOr[bool] = UNDEFINED,
    user_mentions: undefined.UndefinedOr[Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]] = UNDEFINED,
    role_mentions: undefined.UndefinedOr[Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]] = UNDEFINED,
) -> messages_.Message: ...

Inherited from: RESTClient.edit_webhook_message

Edit a message sent by a webhook.

Parameters

webhook : Union[Snowflakeish, ExecutableWebhook]
The webhook to execute. This may be the object or the ID of an existing webhook.
token : str
The webhook token.
message : SnowflakeishOr[PartialMessage]
The message to delete. This may be the object or the ID of an existing message.
content : UndefinedOr[Any]

If provided, the message content to update with. If UNDEFINED, then the content will not be changed. If None, then the content will be removed.

Any other value will be cast to a str before sending.

If this is a Embed and neither the embed or embeds kwargs are provided or if this is a Resourceish and neither the attachment or attachments kwargs are provided, the values will be overwritten. This allows for simpler syntax when sending an embed or an attachment alone.

Other Parameters

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

Whether to replace the attachments with the provided ones. Defaults to False.

Note this will also overwrite the embed attachments.

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

Note

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

Warning

If you specify a non-embed content, mentions_everyone, mentions_reply, user_mentions, and role_mentions will default to False as the message will be re-parsed for mentions.

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

Warning

If you specify one of mentions_everyone, mentions_reply, user_mentions, or role_mentions, then all others will default to False, even if they were enabled previously.

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

Returns

Message
The edited message.

Raises

ValueError
If both attachment and attachments, component and components or embed and embeds are specified.
BadRequestError
This may be raised in several discrete situations, such as messages being empty with no attachments or embeds; messages with more than 2000 characters in them, embeds that exceed one of the many embed limits; too many attachments; attachments that are too large; invalid image URLs in embeds; too many components.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
NotFoundError
If the webhook or the message are not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_webhook_message(
    self,
    webhook: typing.Union[webhooks.ExecutableWebhook, snowflakes.Snowflakeish],
    token: str,
    message: snowflakes.SnowflakeishOr[messages_.Message],
    content: undefined.UndefinedNoneOr[typing.Any] = undefined.UNDEFINED,
    *,
    attachment: undefined.UndefinedOr[files.Resourceish] = undefined.UNDEFINED,
    attachments: undefined.UndefinedOr[typing.Sequence[files.Resourceish]] = undefined.UNDEFINED,
    component: undefined.UndefinedNoneOr[special_endpoints.ComponentBuilder] = undefined.UNDEFINED,
    components: undefined.UndefinedNoneOr[
        typing.Sequence[special_endpoints.ComponentBuilder]
    ] = undefined.UNDEFINED,
    embed: undefined.UndefinedNoneOr[embeds_.Embed] = undefined.UNDEFINED,
    embeds: undefined.UndefinedNoneOr[typing.Sequence[embeds_.Embed]] = undefined.UNDEFINED,
    replace_attachments: bool = False,
    mentions_everyone: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    user_mentions: undefined.UndefinedOr[
        typing.Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]
    ] = undefined.UNDEFINED,
    role_mentions: undefined.UndefinedOr[
        typing.Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]
    ] = undefined.UNDEFINED,
) -> messages_.Message:
    # int(ExecutableWebhook) isn't guaranteed to be valid nor the ID used to execute this entity as a webhook.
    webhook_id = webhook if isinstance(webhook, int) else webhook.webhook_id
    route = routes.PATCH_WEBHOOK_MESSAGE.compile(webhook=webhook_id, token=token, message=message)

    body, form_builder = self._build_message_payload(
        content=content,
        attachment=attachment,
        attachments=attachments,
        component=component,
        components=components,
        embed=embed,
        embeds=embeds,
        replace_attachments=replace_attachments,
        mentions_everyone=mentions_everyone,
        user_mentions=user_mentions,
        role_mentions=role_mentions,
        edit=True,
    )

    if form_builder is not None:
        form_builder.add_field("payload_json", data_binding.dump_json(body), content_type=_APPLICATION_JSON)
        response = await self._request(route, form_builder=form_builder, no_auth=True)
    else:
        response = await self._request(route, json=body, no_auth=True)

    assert isinstance(response, dict)
    return self._entity_factory.deserialize_message(response)
async def edit_welcome_screen(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    *,
    description: undefined.UndefinedNoneOr[str] = UNDEFINED,
    enabled: undefined.UndefinedOr[bool] = UNDEFINED,
    channels: undefined.UndefinedNoneOr[Sequence[guilds.WelcomeChannel]] = UNDEFINED,
) -> WelcomeScreen: ...

Inherited from: RESTClient.edit_welcome_screen

Edit the welcome screen of a community guild.

Parameters

guild : SnowflakeishOr[PartialGuild]
ID or object of the guild to edit the welcome screen for.

Other Parameters

description : undefined.UndefinedNoneOr[str]
If provided, the description to set for the guild's welcome screen. This may be None to unset the description.
enabled : undefined.UndefinedOr[bool]
If provided, Whether the guild's welcome screen should be enabled.
channels : UndefinedNoneOr[Sequence[WelcomeChannel]]

If provided, a sequence of up to 5 public channels to set in this guild's welcome screen. This may be passed as None to remove all welcome channels

Note

Custom emojis may only be included in a guild's welcome channels if it's boost status is tier 2 or above.

Returns

WelcomeScreen
The edited guild welcome screen.

Raises

BadRequestError
If more than 5 welcome channels are provided or if a custom emoji is included on a welcome channel in a guild that doesn't have tier 2 of above boost status or if a private channel is included as a welcome channel.
ForbiddenError
If you are missing the MANAGE_GUILD permission, are not part of the guild or the guild doesn't have access to the community welcome screen feature.
NotFoundError
If the guild is not found.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_welcome_screen(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    *,
    description: undefined.UndefinedNoneOr[str] = undefined.UNDEFINED,
    enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    channels: undefined.UndefinedNoneOr[typing.Sequence[guilds.WelcomeChannel]] = undefined.UNDEFINED,
) -> guilds.WelcomeScreen:
    route = routes.PATCH_GUILD_WELCOME_SCREEN.compile(guild=guild)

    body = data_binding.JSONObjectBuilder()

    body.put("description", description)
    body.put("enabled", enabled)

    if channels is not None:
        body.put_array("welcome_channels", channels, conversion=self._entity_factory.serialize_welcome_channel)

    else:
        body.put("welcome_channels", None)

    response = await self._request(route, json=body)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_welcome_screen(response)
async def edit_widget(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    *,
    channel: undefined.UndefinedNoneOr[snowflakes.SnowflakeishOr[channels_.GuildChannel]] = UNDEFINED,
    enabled: undefined.UndefinedOr[bool] = UNDEFINED,
    reason: undefined.UndefinedOr[str] = UNDEFINED,
) -> GuildWidget: ...

Inherited from: RESTClient.edit_widget

Fetch a guilds's widget.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to edit the widget in. This can be the object or the ID of an existing guild.

Other Parameters

channel : UndefinedNoneOr[SnowflakeishOr[GuildChannel]]
If provided, the channel to set the widget to. If None, will not set to any.
enabled : UndefinedOr[bool]
If provided, whether to enable the widget.
reason : UndefinedOr[str]
If provided, the reason that will be recorded in the audit logs. Maximum of 512 characters.

Returns

GuildWidget
The edited guild widget.

Raises

ForbiddenError
If you are missing the MANAGE_GUILD permission.
NotFoundError
If the guild is not found.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def edit_widget(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    *,
    channel: undefined.UndefinedNoneOr[snowflakes.SnowflakeishOr[channels_.GuildChannel]] = undefined.UNDEFINED,
    enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
    reason: undefined.UndefinedOr[str] = undefined.UNDEFINED,
) -> guilds.GuildWidget:
    route = routes.PATCH_GUILD_WIDGET.compile(guild=guild)

    body = data_binding.JSONObjectBuilder()
    body.put("enabled", enabled)
    if channel is None:
        body.put("channel", None)
    elif channel is not undefined.UNDEFINED:
        body.put_snowflake("channel", channel)

    response = await self._request(route, json=body, reason=reason)
    assert isinstance(response, dict)
    return self._entity_factory.deserialize_guild_widget(response)
async def estimate_guild_prune_count(
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    *,
    days: undefined.UndefinedOr[int] = UNDEFINED,
    include_roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = UNDEFINED,
) -> int: ...

Inherited from: RESTClient.estimate_guild_prune_count

Estimate the guild prune count.

Parameters

guild : SnowflakeishOr[PartialGuild]
The guild to estimate the guild prune count for. This may be the object or the ID of an existing guild.

Other Parameters

days : UndefinedOr[int]
If provided, number of days to count prune for.
include_roles : UndefinedOr[SnowflakeishSequence[PartialRole]]]
If provided, the role(s) to include. By default, this endpoint will not count users with roles. Providing roles using this attribute will make members with the specified roles also get included into the count.

Returns

int
The estimated guild prune count.

Raises

BadRequestError
If any of the fields that are passed have an invalid value.
UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
ForbiddenError
If you are missing the KICK_MEMBERS permission.
NotFoundError
If the guild is not found.
RateLimitTooLongError
Raised in the event that a rate limit occurs that is longer than max_rate_limit when making a request.
RateLimitedError
Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur.
InternalServerError
If an internal error occurs on Discord while handling the request.
Expand source code
Browse git
async def estimate_guild_prune_count(
    self,
    guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
    *,
    days: undefined.UndefinedOr[int] = undefined.UNDEFINED,
    include_roles: undefined.UndefinedOr[snowflakes.SnowflakeishSequence[guilds.PartialRole]] = undefined.UNDEFINED,
) -> int:
    route = routes.GET_GUILD_PRUNE.compile(guild=guild)
    query = data_binding.StringMapBuilder()
    query.put("days", days)
    if include_roles is not undefined.UNDEFINED:
        roles = ",".join(str(int(role)) for role in include_roles)
        query.put("include_roles", roles)
    response = await self._request(route, query=query)
    assert isinstance(response, dict)
    return int(response["pruned"])
async def execute_webhook(
    webhook: Union[webhooks.ExecutableWebhooksnowflakes.Snowflakeish],
    token: str,
    content: undefined.UndefinedOr[Any] = UNDEFINED,
    *,
    username: undefined.UndefinedOr[str] = UNDEFINED,
    avatar_url: Union[undefined.UndefinedTypestrfiles.URL] = UNDEFINED,
    attachment: undefined.UndefinedOr[files.Resourceish] = UNDEFINED,
    attachments: undefined.UndefinedOr[Sequence[files.Resourceish]] = UNDEFINED,
    component: undefined.UndefinedOr[special_endpoints.ComponentBuilder] = UNDEFINED,
    components: undefined.UndefinedOr[Sequence[special_endpoints.ComponentBuilder]] = UNDEFINED,
    embed: undefined.UndefinedOr[embeds_.Embed] = UNDEFINED,
    embeds: undefined.UndefinedOr[Sequence[embeds_.Embed]] = UNDEFINED,
    tts: undefined.UndefinedOr[bool] = UNDEFINED,
    mentions_everyone: undefined.UndefinedOr[bool] = UNDEFINED,
    user_mentions: undefined.UndefinedOr[Union[snowflakes.SnowflakeishSequence[users.PartialUser], bool]] = UNDEFINED,
    role_mentions: undefined.UndefinedOr[Union[snowflakes.SnowflakeishSequence[guilds.PartialRole], bool]] = UNDEFINED,
    flags: Union[undefined.UndefinedTypeintmessages_.MessageFlag] = UNDEFINED,
) -> messages_.Message: ...

Inherited from: RESTClient.execute_webhook

Execute a webhook.

Parameters

webhook : Union[Snowflakeish, ExecutableWebhook]
The webhook to execute. This may be the object or the ID of an existing webhook.
token : str
The webhook token.
content : UndefinedOr[Any]

If provided, the message contents. If UNDEFINED, then nothing will be sent in the content. Any other value here will be cast to a str.

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

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

Other Parameters

username : UndefinedOr[