Source code for hikari.applications

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

from __future__ import annotations

__all__: typing.Sequence[str] = (
    "InviteApplication",
    "Application",
    "ApplicationFlags",
    "AuthorizationApplication",
    "AuthorizationInformation",
    "ConnectionVisibility",
    "OAuth2AuthorizationToken",
    "OAuth2ImplicitToken",
    "OAuth2Scope",
    "OwnConnection",
    "OwnGuild",
    "OwnApplicationRoleConnection",
    "PartialOAuth2Token",
    "Team",
    "TeamMember",
    "TeamMembershipState",
    "TokenType",
    "ApplicationRoleConnectionMetadataRecordType",
    "ApplicationRoleConnectionMetadataRecord",
    "get_token_id",
)

import base64
import typing

import attr

from hikari import guilds
from hikari import locales
from hikari import snowflakes
from hikari import urls
from hikari import users
from hikari.internal import attr_extensions
from hikari.internal import enums
from hikari.internal import routes

if typing.TYPE_CHECKING:
    import datetime

    from hikari import colors
    from hikari import files
    from hikari import permissions as permissions_
    from hikari import traits
    from hikari import webhooks


@typing.final
[docs]class ApplicationFlags(enums.Flag): """The known application flag bits."""
[docs] VERIFIED_FOR_GUILD_PRESENCES = 1 << 12
"""Denotes that a verified application can use the GUILD_PRESENCES intent."""
[docs] GUILD_PRESENCES_INTENT = 1 << 13
"""Denotes that the application has the GUILD_PRESENCES intent enabled in it's dashboard."""
[docs] VERIFIED_FOR_GUILD_MEMBERS_INTENT = 1 << 14
"""Denotes that a verified application can use the GUILD_MEMBERS intent."""
[docs] GUILD_MEMBERS_INTENT = 1 << 15
"""Denotes that the application has the GUILD_MEMBERS intent enabled in it's dashboard."""
[docs] VERIFICATION_PENDING_GUILD_LIMIT = 1 << 16
"""Denotes that the application's verification is pending."""
[docs] EMBEDDED = 1 << 17
"""Denotes that the application has functionality that's specially embedded in Discord's client."""
[docs] MESSAGE_CONTENT_INTENT = 1 << 18
"""Denotes that the application has message content intent enabled in it's dashboard."""
[docs] MESSAGE_CONTENT_INTENT_LIMITED = 1 << 19
"""Denotes that the application has message content access while pending verification."""
[docs] APPLICATION_COMMAND_BADGE = 1 << 23
"""Denotes that the application has at least one global application command."""
@typing.final
[docs]class OAuth2Scope(str, enums.Enum): """OAuth2 Scopes that Discord allows. These are categories of permissions for applications using the OAuth2 API directly. Most users will only ever need the `BOT` scope when developing bots. """
[docs] ACTIVITIES_READ = "activities.read"
"""Enables fetching the "Now Playing/Recently Played" list. .. note:: You must be whitelisted to use this scope. """
[docs] ACTIVITIES_WRITE = "activities.write"
"""Enables updating a user's activity. .. note:: You must be whitelisted to use this scope. .. note:: This is not required to use the GameSDK activity manager. """
[docs] APPLICATIONS_BUILDS_READ = "applications.builds.read"
"""Enables reading build data for a user's applications. .. note:: You must be whitelisted to use this scope. """
[docs] APPLICATIONS_BUILDS_UPLOAD = "applications.builds.upload"
"""Enables uploading/updating builds for a user's applications. .. note:: You must be whitelisted to use this scope. """
[docs] APPLICATIONS_COMMANDS = "applications.commands"
"""Allows your application's commands to be used in a guild. This is used in Discord's special Bot Authorization Flow like `OAuth2Scope.BOT` in-order to join an application into a guild as an application command providing integration. """
[docs] APPLICATIONS_COMMANDS_UPDATE = "applications.commands.update"
"""Allows your application to update its commands via a bearer token."""
[docs] APPLICATIONS_COMMANDS_PERMISSION_UPDATE = "applications.commands.permissions.update"
"""Allows your application to update its commands permissions via a bearer token."""
[docs] APPLICATIONS_ENTITLEMENTS = "applications.entitlements"
"""Enables reading entitlements for a user's applications."""
[docs] APPLICATIONS_STORE_UPDATE = "applications.store.update"
"""Enables reading/updating store data for the user's applications. This includes store listings, achievements, SKU's, etc. .. note:: The store API is deprecated and may be removed in the future. """
[docs] BOT = "bot"
"""Enables adding a bot application to a guild. .. note:: This requires you to have set up a bot account for your application. """
[docs] CONNECTIONS = "connections"
"""Enables viewing third-party linked accounts such as Twitch."""
[docs] EMAIL = "email"
"""Enable the application to view the user's email and application info."""
[docs] GROUP_DM_JOIN = "gdm.join"
"""Enables joining users into a group DM. .. warning:: This cannot add the bot to a group DM. """
[docs] GUILDS = "guilds"
"""Enables viewing the guilds the user is in."""
[docs] GUILDS_JOIN = "guilds.join"
"""Enables adding the user to a specific guild. .. note:: This requires you to have set up a bot account for your application. """
[docs] IDENTIFY = "identify"
"""Enables viewing info about itself. .. note:: This does not include email address info. Use the `EMAIL` scope instead to retrieve this information. """
[docs] RELATIONSHIPS_READ = "relationships.read"
"""Enables viewing a user's friend list. .. note:: You must be whitelisted to use this scope. """
[docs] RPC = "rpc"
"""Enables the RPC application to control the local user's Discord client. .. note:: You must be whitelisted to use this scope. """
[docs] RPC_MESSAGES_READ = "messages.read"
"""Enables the RPC application to read messages from all channels the user is in."""
[docs] RPC_NOTIFICATIONS_READ = "rpc.notifications.read"
"""Enables the RPC application to read from all channels the user is in. .. note:: You must be whitelisted to use this scope. """
[docs] WEBHOOK_INCOMING = "webhook.incoming"
"""Used to generate a webhook that is returned in the OAuth2 token response. This is used during authorization code grants. """
[docs] GUILDS_MEMBERS_READ = "guilds.members.read"
"""Used to read the current user's guild members."""
[docs] ROLE_CONNECTIONS_WRITE = "role_connections.write"
"""Used to write to the current user's connection and metadata for the app."""
@typing.final
[docs]class ConnectionVisibility(int, enums.Enum): """Describes who can see a connection with a third party account."""
[docs] NONE = 0
"""Implies that only you can see the corresponding connection."""
[docs] EVERYONE = 1
"""Everyone can see the connection."""
@attr_extensions.with_copy @attr.define(hash=True, kw_only=True, weakref_slot=False)
[docs]class OwnConnection: """Represents a user's connection with a third party account. Returned by the `GET Current User Connections` endpoint. """
[docs] id: str = attr.field(hash=True, repr=True)
"""The string ID of the third party connected account. .. warning:: Seeing as this is a third party ID, it will not be a snowflakes. """
[docs] name: str = attr.field(eq=False, hash=False, repr=True)
"""The username of the connected account."""
[docs] type: str = attr.field(eq=False, hash=False, repr=True)
"""The type of service this connection is for."""
[docs] is_revoked: bool = attr.field(eq=False, hash=False, repr=False)
"""`True` if the connection has been revoked."""
[docs] integrations: typing.Sequence[guilds.PartialIntegration] = attr.field(eq=False, hash=False, repr=False)
"""A sequence of the partial guild integration objects this connection has."""
[docs] is_verified: bool = attr.field(eq=False, hash=False, repr=False)
"""`True` if the connection has been verified."""
[docs] is_friend_sync_enabled: bool = attr.field(eq=False, hash=False, repr=False)
"""`True` if friends should be added based on this connection."""
[docs] is_activity_visible: bool = attr.field(eq=False, hash=False, repr=False)
"""`True` if this connection's activities are shown in the user's presence."""
[docs] visibility: typing.Union[ConnectionVisibility, int] = attr.field(eq=False, hash=False, repr=True)
"""The visibility of the connection."""
@attr.define(hash=True, kw_only=True, weakref_slot=False)
[docs]class OwnGuild(guilds.PartialGuild): """Represents a user bound partial guild object."""
[docs] features: typing.Sequence[typing.Union[str, guilds.GuildFeature]] = attr.field(eq=False, hash=False, repr=False)
"""A list of the features in this guild."""
[docs] is_owner: bool = attr.field(eq=False, hash=False, repr=True)
"""`True` when the current user owns this guild."""
[docs] my_permissions: permissions_.Permissions = attr.field(eq=False, hash=False, repr=False)
"""The guild-level permissions that apply to the current user or bot."""
@attr.define(hash=True, kw_only=True, weakref_slot=False)
[docs]class OwnApplicationRoleConnection: """Represents an own application role connection."""
[docs] platform_name: typing.Optional[str] = attr.field(eq=True, hash=True, repr=True)
"""The name of the platform."""
[docs] platform_username: typing.Optional[str] = attr.field(eq=True, hash=True, repr=True)
"""The users name in the platform."""
[docs] metadata: typing.Mapping[str, str] = attr.field(eq=False, hash=False, repr=False)
"""Mapping application role connection metadata keys to their value. .. note:: Unfortunately, these can't be deserialized to their proper types as Discord don't provide a way to difference between them. You can deserialize them yourself based on what value you expect from the key: - `INTEGER_X`: Cast to an `int`. - `DATETIME_X`: Cast to a `datetime.datetime.fromisoformat` or `ciso8601.parse_rfc3339` for speed. - `BOOLEAN_X`: Cast to a `bool`. """
@typing.final
[docs]class TeamMembershipState(int, enums.Enum): """Represents the state of a user's team membership."""
[docs] INVITED = 1
"""Denotes the user has been invited to the team but has yet to accept."""
[docs] ACCEPTED = 2
"""Denotes the user has accepted the invite and is now a member."""
@attr_extensions.with_copy @attr.define(eq=False, hash=False, kw_only=True, weakref_slot=False)
[docs]class TeamMember(users.User): """Represents a member of a Team."""
[docs] membership_state: typing.Union[TeamMembershipState, int] = attr.field(repr=False)
"""The state of this user's membership."""
[docs] permissions: typing.Sequence[str] = attr.field(repr=False)
"""This member's permissions within a team. At the time of writing, this will always be a sequence of one `str`, which will always be `"*"`. This may change in the future, however. """
[docs] team_id: snowflakes.Snowflake = attr.field(repr=True)
"""The ID of the team this member belongs to."""
[docs] user: users.User = attr.field(repr=True)
"""The user representation of this team member.""" @property
[docs] def app(self) -> traits.RESTAware: """Return the app that is bound to the user object.""" return self.user.app
@property def avatar_hash(self) -> typing.Optional[str]: return self.user.avatar_hash @property def avatar_url(self) -> typing.Optional[files.URL]: return self.user.avatar_url @property def default_avatar_url(self) -> files.URL: return self.user.default_avatar_url @property def banner_hash(self) -> typing.Optional[str]: return self.user.banner_hash @property def banner_url(self) -> typing.Optional[files.URL]: return self.user.banner_url @property def accent_color(self) -> typing.Optional[colors.Color]: return self.user.accent_color @property def discriminator(self) -> str: return self.user.discriminator @property def flags(self) -> users.UserFlag: return self.user.flags @property def id(self) -> snowflakes.Snowflake: return self.user.id @property def is_bot(self) -> bool: return self.user.is_bot @property def is_system(self) -> bool: return self.user.is_system @property def mention(self) -> str: return self.user.mention @property def username(self) -> str: return self.user.username def __str__(self) -> str: return str(self.user) def __hash__(self) -> int: return hash(self.user) def __eq__(self, other: object) -> bool: return self.user == other
@attr_extensions.with_copy @attr.define(hash=True, kw_only=True, weakref_slot=False)
[docs]class Team(snowflakes.Unique): """Represents a development team, along with all its members."""
[docs] app: traits.RESTAware = attr.field( repr=False, eq=False, hash=False, metadata={attr_extensions.SKIP_DEEP_COPY: True} )
"""Client application that models may use for procedures."""
[docs] id: snowflakes.Snowflake = attr.field(hash=True, repr=True)
"""The ID of this entity."""
[docs] name: str = attr.field(hash=False, eq=False, repr=True)
"""The name of this team."""
[docs] icon_hash: typing.Optional[str] = attr.field(eq=False, hash=False, repr=False)
"""The CDN hash of this team's icon. If no icon is provided, this will be `None`. """
[docs] members: typing.Mapping[snowflakes.Snowflake, TeamMember] = attr.field(eq=False, hash=False, repr=False)
"""A mapping containing each member in this team. The mapping maps keys containing the member's ID to values containing the member object. """
[docs] owner_id: snowflakes.Snowflake = attr.field(eq=False, hash=False, repr=True)
"""The ID of this team's owner.""" def __str__(self) -> str: return f"Team {self.name} ({self.id})" @property
[docs] def icon_url(self) -> typing.Optional[files.URL]: """Icon URL, or `None` if no icon exists.""" return self.make_icon_url()
[docs] def make_icon_url(self, *, ext: str = "png", size: int = 4096) -> typing.Optional[files.URL]: """Generate the icon URL for this team if set. Parameters ---------- ext : str The extension to use for this URL, defaults to `png`. Supports `png`, `jpeg`, `jpg` and `webp`. size : int The size to set for the URL, defaults to `4096`. Can be any power of two between `16` and `4096` inclusive. Returns ------- typing.Optional[hikari.files.URL] The URL, or `None` if no icon exists. Raises ------ ValueError If the size is not an integer power of 2 between 16 and 4096 (inclusive). """ if self.icon_hash is None: return None return routes.CDN_TEAM_ICON.compile_to_file( urls.CDN_URL, team_id=self.id, hash=self.icon_hash, size=size, file_format=ext, )
@attr_extensions.with_copy @attr.define(hash=True, kw_only=True, weakref_slot=False)
[docs]class InviteApplication(guilds.PartialApplication): """Represents the information of an Invite Application."""
[docs] app: traits.RESTAware = attr.field( repr=False, eq=False, hash=False, metadata={attr_extensions.SKIP_DEEP_COPY: True} )
"""Client application that models may use for procedures."""
[docs] cover_image_hash: typing.Optional[str] = attr.field(eq=False, hash=False, repr=False)
"""The CDN's hash of this application's default rich presence invite cover image."""
[docs] public_key: bytes = attr.field(eq=False, hash=False, repr=False)
"""The key used for verifying interaction and GameSDK payload signatures.""" @property
[docs] def cover_image_url(self) -> typing.Optional[files.URL]: """Rich presence cover image URL for this application, if set.""" return self.make_cover_image_url()
[docs] def make_cover_image_url(self, *, ext: str = "png", size: int = 4096) -> typing.Optional[files.URL]: """Generate the rich presence cover image URL for this application, if set. Parameters ---------- ext : str The extension to use for this URL, defaults to `png`. Supports `png`, `jpeg`, `jpg` and `webp`. size : int The size to set for the URL, defaults to `4096`. Can be any power of two between 16 and 4096. Returns ------- typing.Optional[hikari.files.URL] The URL, or `None` if no cover image exists. Raises ------ ValueError If the size is not an integer power of 2 between 16 and 4096 (inclusive). """ if self.cover_image_hash is None: return None return routes.CDN_APPLICATION_COVER.compile_to_file( urls.CDN_URL, application_id=self.id, hash=self.cover_image_hash, size=size, file_format=ext, )
@attr_extensions.with_copy @attr.define(hash=True, kw_only=True, weakref_slot=False) class ApplicationInstallParameters: """Represents the application install parameters.""" scopes: typing.Sequence[str] = attr.field(eq=True, repr=False, hash=True) """The scopes to authorize the bot for.""" permissions: permissions_.Permissions = attr.field(eq=True, repr=False, hash=True) """The permissions to add the bot to guild with.""" @attr_extensions.with_copy @attr.define(hash=True, kw_only=True, weakref_slot=False)
[docs]class Application(guilds.PartialApplication): """Represents the information of an Oauth2 Application."""
[docs] app: traits.RESTAware = attr.field( repr=False, eq=False, hash=False, metadata={attr_extensions.SKIP_DEEP_COPY: True} )
"""Client application that models may use for procedures."""
[docs] is_bot_public: bool = attr.field(eq=False, hash=False, repr=True)
"""`True` if the bot associated with this application is public."""
[docs] is_bot_code_grant_required: bool = attr.field(eq=False, hash=False, repr=False)
"""`True` if this application's bot is requiring code grant for invites."""
[docs] owner: users.User = attr.field(eq=False, hash=False, repr=True)
"""The application's owner."""
[docs] rpc_origins: typing.Optional[typing.Sequence[str]] = attr.field(eq=False, hash=False, repr=False)
"""A collection of this application's RPC origin URLs, if RPC is enabled."""
[docs] flags: ApplicationFlags = attr.field(eq=False, hash=False, repr=False)
"""The flags for this application."""
[docs] public_key: bytes = attr.field(eq=False, hash=False, repr=False)
"""The key used for verifying interaction and GameSDK payload signatures."""
[docs] team: typing.Optional[Team] = attr.field(eq=False, hash=False, repr=False)
"""The team this application belongs to. If the application is not part of a team, this will be `None`. """
[docs] cover_image_hash: typing.Optional[str] = attr.field(eq=False, hash=False, repr=False)
"""The CDN's hash of this application's default rich presence invite cover image."""
[docs] terms_of_service_url: typing.Optional[str] = attr.field(eq=False, hash=False, repr=False)
"""The URL of this application's terms of service."""
[docs] privacy_policy_url: typing.Optional[str] = attr.field(eq=False, hash=False, repr=False)
"""The URL of this application's privacy policy."""
[docs] role_connections_verification_url: typing.Optional[str] = attr.field(eq=False, hash=False, repr=False)
"""The URL of this application's role connection verification entry point."""
[docs] custom_install_url: typing.Optional[str] = attr.field(eq=False, hash=False, repr=False)
"""The URL of this application's custom authorization link."""
[docs] tags: typing.Sequence[str] = attr.field(eq=False, hash=False, repr=False)
"""A sequence of tags describing the content and functionality of the application."""
[docs] install_parameters: typing.Optional[ApplicationInstallParameters] = attr.field(eq=False, hash=False, repr=False)
"""Settings for the application's default in-app authorization link, if enabled.""" @property
[docs] def cover_image_url(self) -> typing.Optional[files.URL]: """Rich presence cover image URL for this application, if set.""" return self.make_cover_image_url()
[docs] def make_cover_image_url(self, *, ext: str = "png", size: int = 4096) -> typing.Optional[files.URL]: """Generate the rich presence cover image URL for this application, if set. Parameters ---------- ext : str The extension to use for this URL, defaults to `png`. Supports `png`, `jpeg`, `jpg` and `webp`. size : int The size to set for the URL, defaults to `4096`. Can be any power of two between 16 and 4096. Returns ------- typing.Optional[hikari.files.URL] The URL, or `None` if no cover image exists. Raises ------ ValueError If the size is not an integer power of 2 between 16 and 4096 (inclusive). """ if self.cover_image_hash is None: return None return routes.CDN_APPLICATION_COVER.compile_to_file( urls.CDN_URL, application_id=self.id, hash=self.cover_image_hash, size=size, file_format=ext, )
@attr_extensions.with_copy @attr.define(hash=True, kw_only=True, weakref_slot=False)
[docs]class AuthorizationApplication(guilds.PartialApplication): """The application model found attached to `AuthorizationInformation`."""
[docs] public_key: bytes = attr.field(eq=False, hash=False, repr=False)
"""The key used for verifying interaction and GameSDK payload signatures."""
[docs] is_bot_public: typing.Optional[bool] = attr.field(eq=False, hash=False, repr=True)
"""`True` if the bot associated with this application is public. Will be `None` if this application doesn't have an associated bot. """
[docs] is_bot_code_grant_required: typing.Optional[bool] = attr.field(eq=False, hash=False, repr=False)
"""`True` if this application's bot is requiring code grant for invites. Will be `None` if this application doesn't have a bot. """
[docs] terms_of_service_url: typing.Optional[str] = attr.field(eq=False, hash=False, repr=False)
"""The URL of this application's terms of service."""
[docs] privacy_policy_url: typing.Optional[str] = attr.field(eq=False, hash=False, repr=False)
"""The URL of this application's privacy policy."""
@attr_extensions.with_copy @attr.define(hash=False, kw_only=True, weakref_slot=False)
[docs]class AuthorizationInformation: """Model for the data returned by Get Current Authorization Information."""
[docs] application: AuthorizationApplication = attr.field(hash=False, repr=True)
"""The current application."""
[docs] expires_at: datetime.datetime = attr.field(hash=False, repr=True)
"""When the access token this data was retrieved with expires."""
[docs] scopes: typing.Sequence[typing.Union[OAuth2Scope, str]] = attr.field(hash=False, repr=True)
"""A sequence of the scopes the current user has authorized the application for."""
[docs] user: typing.Optional[users.User] = attr.field(hash=False, repr=True)
"""The user who has authorized this token if they included the `identify` scope."""
@attr_extensions.with_copy @attr.define(hash=True, kw_only=True, weakref_slot=False)
[docs]class PartialOAuth2Token: """Model for partial OAuth2 token data returned by the API. This will generally only be returned when by the client credentials OAuth2 flow. """
[docs] access_token: str = attr.field(hash=True, repr=False)
"""Access token issued by the authorization server."""
[docs] token_type: typing.Union[TokenType, str] = attr.field(eq=False, hash=False, repr=True)
"""Type of token issued by the authorization server."""
[docs] expires_in: datetime.timedelta = attr.field(eq=False, hash=False, repr=True)
"""Lifetime of this access token."""
[docs] scopes: typing.Sequence[typing.Union[OAuth2Scope, str]] = attr.field(eq=False, hash=False, repr=True)
"""Scopes the access token has access to.""" def __str__(self) -> str: return self.access_token
@attr_extensions.with_copy @attr.define(hash=True, kw_only=True, weakref_slot=False)
[docs]class OAuth2AuthorizationToken(PartialOAuth2Token): """Model for the OAuth2 token data returned by the authorization grant flow."""
[docs] refresh_token: int = attr.field(eq=False, hash=False, repr=False)
"""Refresh token used to obtain new access tokens with the same grant."""
[docs] webhook: typing.Optional[webhooks.IncomingWebhook] = attr.field(eq=False, hash=False, repr=True)
"""Object of the webhook that was created. This will only be present if this token was authorized with the `webhooks.incoming` scope, otherwise this will be `None`. """
[docs] guild: typing.Optional[guilds.RESTGuild] = attr.field(eq=False, hash=False, repr=True)
"""Object of the guild the user was added to. This will only be present if this token was authorized with the `bot` scope, otherwise this will be `None`. """
@attr_extensions.with_copy @attr.define(hash=True, kw_only=True, weakref_slot=False)
[docs]class OAuth2ImplicitToken(PartialOAuth2Token): """Model for the OAuth2 token data returned by the implicit grant flow."""
[docs] state: typing.Optional[str] = attr.field(eq=False, hash=False, repr=False)
"""State parameter that was present in the authorization request if provided."""
@typing.final
[docs]class TokenType(str, enums.Enum): """Token types used within Hikari clients."""
[docs] BOT = "Bot"
"""Bot token type."""
[docs] BASIC = "Basic"
"""OAuth2 basic token type."""
[docs] BEARER = "Bearer"
"""OAuth2 bearer token type."""
@typing.final
[docs]class ApplicationRoleConnectionMetadataRecordType(int, enums.Enum): """Represents possible application role connection metadata record types."""
[docs] INTEGER_LESS_THAN_OR_EQUAL = 1
"""Integer Less Than Or Equal."""
[docs] INTEGER_GREATER_THAN_OR_EQUAL = 2
"""Integer Greater Than Or Equal."""
[docs] INTEGER_EQUAL = 3
"""Integer Equal."""
[docs] INTEGER_NOT_EQUAL = 4
"""Integer Not Equal."""
[docs] DATETIME_LESS_THAN_OR_EQUAL = 5
"""Datetime Less Than Or Equal."""
[docs] DATETIME_GREATER_THAN_OR_EQUAL = 6
"""Datetime Greater Than Or Equal."""
[docs] BOOLEAN_EQUAL = 7
"""Boolean Equal."""
[docs] BOOLEAN_NOT_EQUAL = 8
"""Boolean Not Equal."""
@attr.define(hash=True, kw_only=True, weakref_slot=False)
[docs]class ApplicationRoleConnectionMetadataRecord: """Represents a role connection metadata record."""
[docs] type: typing.Union[ApplicationRoleConnectionMetadataRecordType, int] = attr.field(eq=False, hash=False, repr=False)
"""The type of metadata value record."""
[docs] key: str = attr.field(eq=True, hash=True, repr=False)
"""Dictionary key for the metadata field."""
[docs] name: str = attr.field(eq=False, hash=False, repr=True)
"""The metadata's field name."""
[docs] description: str = attr.field(eq=False, hash=False, repr=True)
"""The metadata's field description."""
[docs] name_localizations: typing.Mapping[typing.Union[locales.Locale, str], str] = attr.field( eq=False, hash=False, repr=False, factory=dict, )
"""A mapping of name localizations for this metadata field."""
[docs] description_localizations: typing.Mapping[typing.Union[locales.Locale, str], str] = attr.field( eq=False, hash=False, repr=False, factory=dict, )
"""A mapping of description localizations for this metadata field."""
[docs]def get_token_id(token: str) -> snowflakes.Snowflake: """Try to get the bot ID stored in a token. Returns ------- hikari.snowflakes.Snowflake The ID that was extracted from the token. Raises ------ ValueError If the passed token has an unexpected format. """ try: segment = token.split(".", 1)[0] # I don't trust Discord to always provide the right amount of padding here as they don't # with the middle field so just to be safe we will add padding here if necessary to avoid # base64.b64decode raising a length or padding error. segment += "=" * (len(segment) % 4) return snowflakes.Snowflake(base64.b64decode(segment)) except (TypeError, ValueError, IndexError) as exc: raise ValueError("Unexpected token format") from exc