class KnownCustomEmoji(CustomEmoji): """Represents an emoji that is known from a guild the bot is in. This is a specialization of `CustomEmoji` that is from a guild that you _are_ part of. As a result, it contains a lot more information with it. """ app: traits.RESTAware = attr.field( repr=False, eq=False, hash=False, metadata={attr_extensions.SKIP_DEEP_COPY: True} ) """The client application that models may use for procedures.""" guild_id: snowflakes.Snowflake = attr.field(eq=False, hash=False, repr=False) """The ID of the guild this emoji belongs to.""" role_ids: typing.Sequence[snowflakes.Snowflake] = attr.field(eq=False, hash=False, repr=False) """The IDs of the roles that are whitelisted to use this emoji. If this is empty then any user can use this emoji regardless of their roles. """ user: typing.Optional[users.User] = attr.field(eq=False, hash=False, repr=False) """The user that created the emoji. !!! note This will be `builtins.None` if you are missing the `MANAGE_EMOJIS` permission in the server the emoji is from. """ is_animated: bool = attr.field(eq=False, hash=False, repr=True) """Whether the emoji is animated. Unlike in `CustomEmoji`, this information is always known, and will thus never be `builtins.None`. """ is_colons_required: bool = attr.field(eq=False, hash=False, repr=False) """Whether this emoji must be wrapped in colons.""" is_managed: bool = attr.field(eq=False, hash=False, repr=False) """Whether the emoji is managed by an integration.""" is_available: bool = attr.field(eq=False, hash=False, repr=False) """Whether this emoji can currently be used.
class OwnConnection: """Represents a user's connection with a third party account. Returned by the `GET Current User Connections` endpoint. """ 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. """ name: str = attr.field(eq=False, hash=False, repr=True) """The username of the connected account.""" type: str = attr.field(eq=False, hash=False, repr=True) """The type of service this connection is for.""" is_revoked: bool = attr.field(eq=False, hash=False, repr=False) """`builtins.True` if the connection has been revoked.""" integrations: typing.Sequence[guilds.PartialIntegration] = attr.field( eq=False, hash=False, repr=False) """A sequence of the partial guild integration objects this connection has.""" is_verified: bool = attr.field(eq=False, hash=False, repr=False) """`builtins.True` if the connection has been verified.""" is_friend_sync_enabled: bool = attr.field(eq=False, hash=False, repr=False) """`builtins.True` if friends should be added based on this connection.""" is_activity_visible: bool = attr.field(eq=False, hash=False, repr=False) """`builtins.True` if this connection's activities are shown in the user's presence.""" visibility: typing.Union[ConnectionVisibility, int] = attr.field(eq=False, hash=False, repr=True) """The visibility of the connection."""
class GatewayGuildDefinition: """A structure for handling entities within guild create and update events.""" guild: guild_models.GatewayGuild = attr.field() """Object of the guild the definition is for.""" channels: typing.Optional[typing.Mapping[ snowflakes.Snowflake, channel_models.GuildChannel]] = attr.field() """Mapping of channel IDs to the channels that belong to the guild. Will be `builtins.None` when returned by guild update gateway events rather than create. """ members: typing.Optional[typing.Mapping[ snowflakes.Snowflake, guild_models.Member]] = attr.field() """Mapping of user IDs to the members that belong to the guild. Will be `builtins.None` when returned by guild update gateway events rather than create. !!! note This may be a partial mapping of members in the guild. """ presences: typing.Optional[typing.Mapping[ snowflakes.Snowflake, presence_models.MemberPresence]] = attr.field() """Mapping of user IDs to the presences that are active in the guild. Will be `builtins.None` when returned by guild update gateway events rather than create. !!! note This may be a partial mapping of presences active in the guild. """ roles: typing.Mapping[snowflakes.Snowflake, guild_models.Role] = attr.field() """Mapping of role IDs to the roles that belong to the guild.""" emojis: typing.Mapping[snowflakes.Snowflake, emoji_models.KnownCustomEmoji] = attr.field() """Mapping of emoji IDs to the emojis that belong to the guild.""" voice_states: typing.Optional[typing.Mapping[ snowflakes.Snowflake, voice_models.VoiceState]] = attr.field() """Mapping of user IDs to the voice states that are active in the guild.
class StartingEvent(base_events.Event): """Event that is triggered before the application connects to discord. This will only fire once per `bot.run` / `bot.start`, so is suitable for opening database connections and other resources that need to be initialized within a coroutine function. !!! warning The application will not proceed to connect to Discord until all event handlers for this event have completed/terminated. This prevents the risk of race conditions occurring (e.g. allowing message events to try to access a database that has not yet connected fully). If you want to do something _after_ the application has initialized, you should consider using `StartedEvent` instead. """ app: traits.RESTAware = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
class FullRepoMetadataConfig: """ Class used with :class:`libcst.metadata.FullRepoManager` config.repo_root_dir """ # `Set[Type[meta.base_provider.BaseMetadataProvider[object]]]`; used as # `frozenset[Variable[_T_co](covariant)]`. providers: Set[ProviderT] = field( default=frozenset([TypeInferenceProvider, FullyQualifiedNameProvider]) ) timeout_seconds: int = 10 repo_root_dir: str = "" batch_size: int = BATCH_SIZE logger: Optional[Logger] = None
class Points(_Shape): """ Represents an ordered set of points. """ class Visibility(Enum): absent = 0 hidden = 1 visible = 2 _type = AnnotationType.points visibility: List[bool] = field(default=None) @visibility.validator def _visibility_validator(self, attribute, visibility): if visibility is None: visibility = [self.Visibility.visible] * (len(self.points) // 2) else: for i, v in enumerate(visibility): if not isinstance(v, self.Visibility): visibility[i] = self.Visibility(v) assert len(visibility) == len(self.points) // 2 self.visibility = visibility def __attrs_post_init__(self): assert len(self.points) % 2 == 0, self.points def get_area(self): return 0 def get_bbox(self): xs = [ p for p, v in zip(self.points[0::2], self.visibility) if v != __class__.Visibility.absent ] ys = [ p for p, v in zip(self.points[1::2], self.visibility) if v != __class__.Visibility.absent ] x0 = min(xs, default=0) x1 = max(xs, default=0) y0 = min(ys, default=0) y1 = max(ys, default=0) return [x0, y0, x1 - x0, y1 - y0]
class KnownCustomEmojiData(BaseData[emojis.KnownCustomEmoji]): """A data model for storing known custom emoji data in an in-memory cache.""" id: snowflakes.Snowflake = attr.field() name: str = attr.field() is_animated: bool = attr.field() guild_id: snowflakes.Snowflake = attr.field() role_ids: typing.Tuple[snowflakes.Snowflake, ...] = attr.field() user: typing.Optional[RefCell[users_.User]] = attr.field() is_colons_required: bool = attr.field() is_managed: bool = attr.field() is_available: bool = attr.field() @classmethod def build_from_entity( cls, emoji: emojis.KnownCustomEmoji, /, *, user: typing.Optional[RefCell[users_.User]] = None, ) -> KnownCustomEmojiData: if not user and emoji.user: user = RefCell(copy.copy(emoji.user)) return cls( id=emoji.id, name=emoji.name, is_animated=emoji.is_animated, guild_id=emoji.guild_id, is_colons_required=emoji.is_colons_required, is_managed=emoji.is_managed, is_available=emoji.is_available, user=user, # role_ids is a special case as it may be a mutable sequence so we want to ensure it's immutable when cached. role_ids=tuple(emoji.role_ids), )
class Request(Generic[ReturnT]): if not typing.TYPE_CHECKING: # ugh there has to be a better way type_args: GenericHolder = attr.field( validator=attr.validators.instance_of(GenericHolder)) method: typing.Literal['GET', 'POST', 'PATCH', 'DELETE', 'PUT'] route: str args: typing.Dict[str, typing.Union[int, str]] params: typing.Optional[typing.Dict[str, typing.Any]] = None json: typing.Optional[typing.Dict[str, typing.Any]] = None headers: typing.Optional[typing.Dict[str, typing.Any]] = None data: typing.Optional[typing.Dict[str, typing.Any]] = None # TODO: better file type? files: typing.Optional[typing.Dict[str, object]] = None @property def url(self) -> str: return self.route.format(**self.args)
class ThreadedFileReader(FileReader): """Asynchronous file reader that reads a resource from local storage. This implementation works with pools that exist in the same interpreter instance as the caller, namely thread pool executors, where objects do not need to be pickled to be communicated. """ _pointer: typing.BinaryIO = attr.field() async def __aiter__(self) -> typing.AsyncGenerator[typing.Any, bytes]: loop = asyncio.get_running_loop() while True: chunk = await loop.run_in_executor(self.executor, self._pointer.read, _MAGIC) yield chunk if len(chunk) < _MAGIC: break
class StoppedEvent(base_events.Event): """Event that is triggered once the application has disconnected. This will only fire once per `bot.close`, so is suitable for closing database connections and other resources that need to be closed within a coroutine function. !!! warning The application will not proceed to leave the `bot.run` call until all event handlers for this event have completed/terminated. This prevents the risk of race conditions occurring where a script may terminate the process before a callback can occur. If you want to do something when the application is preparing to shut down, but _before_ any connection to discord is closed, you should consider using `StoppingEvent` instead. """ app: traits.RESTAware = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
class YataiClientContext: name: str endpoint: str api_token: str email: Optional[str] = attr.field(default=None) def get_yatai_rest_api_client(self) -> YataiRESTApiClient: return YataiRESTApiClient(self.endpoint, self.api_token) def get_email(self) -> str: if not self.email: cli = self.get_yatai_rest_api_client() user = cli.get_current_user() if user is None: raise YataiRESTApiClientError( "Unable to get current user from yatai server") self.email = user.email add_context(self, ignore_warning=True) return self.email
class GuildReactionAddEvent(GuildReactionEvent, ReactionAddEvent): """Event fired when a reaction is added to a guild message.""" shard: gateway_shard.GatewayShard = attr.field( metadata={attr_extensions.SKIP_DEEP_COPY: True}) # <<inherited docstring from ShardEvent>>. member: guilds.Member = attr.field() """Member that added the reaction. Returns ------- hikari.guilds.Member The member which added this reaction. """ channel_id: snowflakes.Snowflake = attr.field() # <<inherited docstring from ReactionEvent>>. message_id: snowflakes.Snowflake = attr.field() # <<inherited docstring from ReactionEvent>>. emoji_name: typing.Union[str, emojis.UnicodeEmoji, None] = attr.field() # <<inherited docstring from ReactionAddEvent>>. emoji_id: typing.Optional[snowflakes.Snowflake] = attr.field() # <<inherited docstring from ReactionAddEvent>>. is_animated: bool = attr.field() # <<inherited docstring from ReactionAddEvent>>. @property def app(self) -> traits.RESTAware: # <<inherited docstring from Event>>. return self.member.app @property def guild_id(self) -> snowflakes.Snowflake: # <<inherited docstring from GuildReactionEvent>>. return self.member.guild_id @property def user_id(self) -> snowflakes.Snowflake: # <<inherited docstring from ReactionAddEvent>>. return self.member.user.id
class CdtAudioDataModule(CdtDataModule[D, I]): root: Union[str, Path] = attr.field(kw_only=False) _train_transforms: Optional[AudioTform] = None _test_transforms: Optional[AudioTform] = None @property @final def train_transforms(self) -> Optional[AudioTform]: return self._train_transforms @train_transforms.setter def train_transforms(self, transform: Optional[AudioTform]) -> None: self._train_transforms = transform if isinstance(self._train_data, AudioTransformer): self._train_data.transform = transform @property @final def test_transforms(self) -> Optional[AudioTform]: return self._test_transforms @test_transforms.setter @final def test_transforms(self, transform: Optional[AudioTform]) -> None: self._test_transforms = transform if isinstance(self._val_data, AudioTransformer): self._val_data.transform = transform if isinstance(self._test_data, AudioTransformer): self._test_data.transform = transform @implements(CdtDataModule) @final def _setup(self, stage: Optional[Stage] = None) -> None: train, val, test = self._get_splits() train = AudioTransformer(train, transform=self.train_transforms) if self.instance_weighting: train = InstanceWeightedDataset(train) self._train_data = train self._val_data = AudioTransformer(val, transform=self.test_transforms) self._test_data = AudioTransformer(test, transform=self.test_transforms)
class StoppingEvent(base_events.Event): """Event that is triggered as soon as the application is requested to close. This will fire before the connection is physically disconnected. This will only fire once per `bot.close`, so is suitable for closing database connections and other resources that need to be closed within a coroutine function. !!! warning The application will not proceed to disconnect from Discord until all event handlers for this event have completed/terminated. This prevents the risk of race conditions occurring from code that relies on a connection still being available to complete. If you want to do something _after_ the disconnection has occurred, you should consider using `StoppedEvent` instead. """ app: traits.RESTAware = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
class HTTPResponseError(HTTPError): """Base exception for an erroneous HTTP response.""" url: str = attr.field() """The URL that produced this error message.""" status: typing.Union[http.HTTPStatus, int] = attr.field() """The HTTP status code for the response. This will be `int` if it's outside the range of status codes in the HTTP specification (e.g. one of Cloudflare's non-standard status codes). """ headers: data_binding.Headers = attr.field() """The headers received in the error response.""" raw_body: typing.Any = attr.field() """The response body.""" message: str = attr.field(default="") """The error message.""" code: int = attr.field(default=0) """The error code.""" def __str__(self) -> str: if isinstance(self.status, http.HTTPStatus): name = self.status.name.replace("_", " ").title() name_value = f"{name} {self.status.value}" else: name_value = f"Unknown Status {self.status}" if self.code: code_str = f" ({self.code})" else: code_str = "" if self.message: body = self.message else: try: body = self.raw_body.decode("utf-8") except (AttributeError, UnicodeDecodeError, TypeError, ValueError): body = str(self.raw_body) chomped = len(body) > 200 return f"{name_value}:{code_str} '{body[:200]}{'...' if chomped else ''}' for {self.url}"
class PatchResourceBuilder: base_dir: Path = field(converter=Path) github_org: str hw_prefix: str tmpl_repo_name: str patch_branch: str def build(self) -> PatchResource: src = self.base_dir / "source_repos" student = self.base_dir / "student_repos" for d in [self.base_dir, src, student]: d.mkdir(exist_ok=True) return PatchResource( base_dir=self.base_dir, src_dir=src, github_org=self.github_org, student_dir=student, tmpl_repo_name=self.tmpl_repo_name, )
class GuildUpdateEvent(GuildEvent): """Event fired when an existing guild is updated.""" app: traits.RESTAware = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True}) # <<inherited docstring from Event>>. shard: gateway_shard.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True}) # <<inherited docstring from ShardEvent>>. old_guild: typing.Optional[guilds.Guild] = attr.field() """The old guild object. This will be `builtins.None` if the guild missing from the cache. """ guild: guilds.GatewayGuild = attr.field() """Guild that was just updated. Returns ------- hikari.guilds.Guild The guild that relates to this event. """ emojis: typing.Mapping[snowflakes.Snowflake, emojis_.KnownCustomEmoji] = attr.field(repr=False) """Mapping of emoji IDs to the emojis in the guild. Returns ------- typing.Mapping[hikari.snowflakes.Snowflake, hikari.emojis.KnownCustomEmoji] The emojis in the guild. """ roles: typing.Mapping[snowflakes.Snowflake, guilds.Role] = attr.field(repr=False) """Mapping of role IDs to the roles in the guild. Returns ------- typing.Mapping[hikari.snowflakes.Snowflake, hikari.guilds.Role] The roles in the guild. """ @property def guild_id(self) -> snowflakes.Snowflake: # <<inherited docstring from GuildEvent>>. return self.guild.id
class MemberMoveEntryInfo(MemberDisconnectEntryInfo): """Extra information for the voice chat based member move entry.""" channel_id: snowflakes.Snowflake = attr.field(repr=True) """The channel that the member(s) have been moved to""" async def fetch_channel(self) -> channels.GuildVoiceChannel: """Fetch the guild voice based channel where the member(s) have been moved to. Returns ------- hikari.channels.GuildVoiceChannel The guild voice based channel where the member(s) have been moved to. Raises ------ hikari.errors.UnauthorizedError If you are unauthorized to make the request (invalid/missing token). hikari.errors.ForbiddenError If you are missing the `READ_MESSAGES` permission in the channel. hikari.errors.NotFoundError If the channel 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. """ channel = await self.app.rest.fetch_channel(self.channel_id) assert isinstance(channel, channels.GuildVoiceChannel) return channel
class InteractionDeferredBuilder(special_endpoints.InteractionDeferredBuilder): """Standard implementation of `hikari.api.special_endpoints.InteractionDeferredBuilder`. Parameters ---------- type : hikari.interactions.bases.DeferredResponseTypesT The type of interaction response this is. """ # Required arguments. _type: base_interactions.DeferredResponseTypesT = attr.field( converter=base_interactions.ResponseType, validator=attr.validators.in_( base_interactions.DEFERRED_RESPONSE_TYPES), ) @property def type(self) -> base_interactions.DeferredResponseTypesT: return self._type def build(self, _: entity_factory_.EntityFactory, /) -> data_binding.JSONObject: return {"type": self.type}
class EmbedResourceWithProxy(EmbedResource[AsyncReaderT]): """Resource with a corresponding proxied element.""" proxy_resource: typing.Optional[files.Resource[AsyncReaderT]] = attr.field( default=None, repr=False) """The proxied version of the resource, or `builtins.None` if not present. !!! note This field cannot be set by bots or webhooks while sending an embed and will be ignored during serialization. Expect this to be populated on any received embed attached to a message event. """ @property @typing.final def proxy_url(self) -> typing.Optional[str]: """Proxied URL of this embed resource if applicable. Returns ------- typing.Optional[builtins.str] The proxied URL of this embed resource if applicable, else `builtins.None`. """ return self.proxy_resource.url if self.proxy_resource else None @property @typing.final def proxy_filename(self) -> typing.Optional[str]: """File name of the proxied version of this embed resource if applicable. Returns ------- typing.Optional[builtins.str] The file name of the proxied version of this embed resource if applicable, else `builtins.None`. """ return self.proxy_resource.filename if self.proxy_resource else None
class WebReader(AsyncReader): """Asynchronous reader to use to read data from a web resource.""" stream: aiohttp.StreamReader = attr.field(repr=False) """The `aiohttp.StreamReader` to read the content from.""" url: str = attr.field(repr=False) """The URL being read from.""" status: int = attr.field() """The initial HTTP response status.""" reason: str = attr.field() """The HTTP response status reason.""" charset: typing.Optional[str] = attr.field() """Optional character set information, if known.""" size: typing.Optional[int] = attr.field() """The size of the resource, if known.""" head_only: bool = attr.field() """If `builtins.True`, then only the HEAD was requested. In this case, neither `__aiter__` nor `read` would return anything other than an empty byte string. """ async def read(self) -> bytes: return b"" if self.head_only else await self.stream.read() async def __aiter__(self) -> typing.AsyncGenerator[typing.Any, bytes]: if self.head_only: yield b"" else: while not self.stream.at_eof(): chunk, _ = await self.stream.readchunk() yield chunk
class ImportComments: before: List[str] = field(factory=list) first_inline: List[str] = field(factory=list) initial: List[str] = field(factory=list) inline: List[str] = field(factory=list) # Only when no trailing comma final: List[str] = field(factory=list) last_inline: List[str] = field(factory=list) def __add__(self, other: "ImportComments") -> "ImportComments": if not isinstance(other, ImportComments): return NotImplemented return ImportComments( before=[*self.before, *other.before], first_inline=[*self.first_inline, *other.first_inline], initial=[*self.initial, *other.initial], inline=[*self.inline, *other.inline], final=[*self.final, *other.final], last_inline=[*self.last_inline, *other.last_inline], )
class GuildSticker(PartialSticker): """Represents a Discord sticker that belongs to a guild.""" type: StickerType = attr.field(eq=False, hash=False, repr=False, init=False, default=StickerType.GUILD) """The sticker type.""" description: typing.Optional[str] = attr.field(eq=False, hash=False, repr=False) """The description of this sticker.""" guild_id: snowflakes.Snowflake = attr.field(eq=False, hash=False) """The guild this sticker belongs to""" is_available: bool = attr.field(eq=False, hash=False) """Whether the sticker can be used.""" tag: str = attr.field(eq=False, hash=False) """This sticker's tag.""" user: typing.Optional[users.User] = attr.field(eq=False, hash=False, repr=False) """The user that uploaded this sticker.
class GuildReactionDeleteEvent(GuildReactionEvent, ReactionDeleteEvent): """Event fired when a reaction is removed from a guild message.""" app: traits.RESTAware = attr.field( metadata={attr_extensions.SKIP_DEEP_COPY: True}) # <<inherited docstring from Event>>. shard: gateway_shard.GatewayShard = attr.field( metadata={attr_extensions.SKIP_DEEP_COPY: True}) # <<inherited docstring from ShardEvent>>. user_id: snowflakes.Snowflake = attr.field() # <<inherited docstring from ReactionAddEvent>>. guild_id: snowflakes.Snowflake = attr.field() # <<inherited docstring from GuildReactionEvent>>. channel_id: snowflakes.Snowflake = attr.field() # <<inherited docstring from ReactionEvent>>. message_id: snowflakes.Snowflake = attr.field() # <<inherited docstring from ReactionEvent>>. emoji: emojis.Emoji = attr.field()
class HTTPResponseError(HTTPError): """Base exception for an erroneous HTTP response.""" url: str = attr.field() """The URL that produced this error message.""" status: http.HTTPStatus = attr.field() """The HTTP status code for the response.""" headers: data_binding.Headers = attr.field() """The headers received in the error response.""" raw_body: typing.Any = attr.field() """The response body.""" message: str = attr.field(default="") """The error message.""" code: int = attr.field(default=0) """The error code.""" def __str__(self) -> str: name = self.status.name.replace("_", " ").title() name_value = f"{name} {self.status.value}" if self.code: code_str = f" ({self.code})" else: code_str = "" if self.message: body = self.message else: try: body = self.raw_body.decode("utf-8") except (AttributeError, UnicodeDecodeError, TypeError, ValueError): body = str(self.raw_body) chomped = len(body) > 200 return f"{name_value}:{code_str} '{body[:200]}{'...' if chomped else ''}' for {self.url}"
class DMReactionDeleteEvent(DMReactionEvent, ReactionDeleteEvent): """Event fired when a reaction is removed from a private message.""" app: traits.RESTAware = attr.field( metadata={attr_extensions.SKIP_DEEP_COPY: True}) # <<inherited docstring from Event>>. shard: gateway_shard.GatewayShard = attr.field( metadata={attr_extensions.SKIP_DEEP_COPY: True}) # <<inherited docstring from ShardEvent>>. user_id: snowflakes.Snowflake = attr.field() # <<inherited docstring from ReactionDeleteEvent>>. channel_id: snowflakes.Snowflake = attr.field() # <<inherited docstring from ReactionEvent>>. message_id: snowflakes.Snowflake = attr.field() # <<inherited docstring from ReactionEvent>>. emoji_name: typing.Union[str, emojis.UnicodeEmoji, None] = attr.field() # <<inherited docstring from ReactionDeleteEvent>>. emoji_id: typing.Optional[snowflakes.Snowflake] = attr.field()
class GuildReactionAddEvent(GuildReactionEvent, ReactionAddEvent): """Event fired when a reaction is added to a guild message.""" app: traits.RESTAware = attr.field( metadata={attr_extensions.SKIP_DEEP_COPY: True}) # <<inherited docstring from Event>>. shard: gateway_shard.GatewayShard = attr.field( metadata={attr_extensions.SKIP_DEEP_COPY: True}) # <<inherited docstring from ShardEvent>>. member: guilds.Member = attr.field() """Member that added the reaction. Returns ------- hikari.guilds.Member The member which added this reaction. """ channel_id: snowflakes.Snowflake = attr.field() # <<inherited docstring from ReactionEvent>>. message_id: snowflakes.Snowflake = attr.field() # <<inherited docstring from ReactionEvent>>. emoji: emojis.Emoji = attr.field() # <<inherited docstring from ReactionAddEvent>>. @property def guild_id(self) -> snowflakes.Snowflake: # <<inherited docstring from GuildReactionEvent>>. return self.member.guild_id @property def user_id(self) -> snowflakes.Snowflake: # <<inherited docstring from ReactionAddEvent>>. return self.member.user.id
class VoiceState: """Represents a user's voice connection status.""" app: traits.RESTAware = attr.field( repr=False, eq=False, hash=False, metadata={attr_extensions.SKIP_DEEP_COPY: True} ) """The client application that models may use for procedures.""" channel_id: typing.Optional[snowflakes.Snowflake] = attr.field(eq=False, hash=False, repr=True) """The ID of the channel this user is connected to. This will be `builtins.None` if they are leaving voice. """ guild_id: snowflakes.Snowflake = attr.field(eq=False, hash=False, repr=True) """The ID of the guild this voice state is in.""" is_guild_deafened: bool = attr.field(eq=False, hash=False, repr=False) """Whether this user is deafened by the guild.""" is_guild_muted: bool = attr.field(eq=False, hash=False, repr=False) """Whether this user is muted by the guild.""" is_self_deafened: bool = attr.field(eq=False, hash=False, repr=False) """Whether this user is deafened by their client.""" is_self_muted: bool = attr.field(eq=False, hash=False, repr=False) """Whether this user is muted by their client.""" is_streaming: bool = attr.field(eq=False, hash=False, repr=False) """Whether this user is streaming using "Go Live".""" is_suppressed: bool = attr.field(eq=False, hash=False, repr=False) """Whether this user is considered to be "suppressed" in a voice context. In the context of a voice channel this may mean that the user is muted by the current user and in the context of a stage channel this means that the user is not a speaker.""" is_video_enabled: bool = attr.field(eq=False, hash=False, repr=False) """Whether this user's camera is enabled.""" user_id: snowflakes.Snowflake = attr.field(eq=False, hash=False, repr=True) """The ID of the user this voice state is for.""" member: guilds.Member = attr.field(eq=False, hash=False, repr=False) """The guild member this voice state is for.""" session_id: str = attr.field(hash=True, repr=True) """The string ID of this voice state's session.""" requested_to_speak_at: typing.Optional[datetime.datetime] = attr.field(eq=False, hash=False, repr=True) """When the user requested to speak in a stage channel.
class ComponentInteraction(base_interactions.MessageResponseMixin[ComponentResponseTypesT]): """Represents a component interaction on Discord.""" channel_id: snowflakes.Snowflake = attr.field(eq=False) """ID of the channel this interaction was triggered in.""" component_type: typing.Union[messages.ComponentType, int] = attr.field(eq=False) """The type of component which triggers this interaction. !!! note This will never be `ButtonStyle.LINK` as link buttons don't trigger interactions. """ custom_id: str = attr.field(eq=False) """Developer defined ID of the component which triggered this interaction.""" values: typing.Sequence[str] = attr.field(eq=False) """Sequence of the values which were selected for a select menu component.""" guild_id: typing.Optional[snowflakes.Snowflake] = attr.field(eq=False) """ID of the guild this interaction was triggered in. This will be `builtins.None` for component interactions triggered in DMs. """ guild_locale: typing.Optional[typing.Union[str, locales.Locale]] = attr.field(eq=False, hash=False, repr=True) """The preferred language of the guild this component interaction was triggered in. This will be `builtins.None` for component interactions triggered in DMs. !!! note This value can usually only be changed if `COMMUNITY` is in `hikari.guilds.Guild.features` for the guild and will otherwise default to `en-US`. """ message: messages.Message = attr.field(eq=False, repr=False) """Object of the message the components for this interaction are attached to.""" member: typing.Optional[base_interactions.InteractionMember] = attr.field(eq=False, hash=False, repr=True) """The member who triggered this interaction. This will be `builtins.None` for interactions triggered in DMs. !!! note This member object comes with the extra field `permissions` which contains the member's permissions in the current channel. """ user: users.User = attr.field(eq=False, hash=False, repr=True) """The user who triggered this interaction.""" locale: typing.Union[str, locales.Locale] = attr.field(eq=False, hash=False, repr=True) """The selected language of the user who triggered this component interaction.""" def build_response(self, type_: _ImmediateTypesT, /) -> special_endpoints.InteractionMessageBuilder: """Get a message response builder for use in the REST server flow. !!! note For interactions received over the gateway `ComponentInteraction.create_initial_response` should be used to set the interaction response message. Parameters ---------- type_ : typing.Union[builtins.int, hikari.interactions.base_interactions.ResponseType] The type of immediate response this should be. This may be one of the following: * `hikari.interactions.base_interactions.ResponseType.MESSAGE_CREATE` * `hikari.interactions.base_interactions.ResponseType.MESSAGE_UPDATE` Examples -------- ```py async def handle_component_interaction(interaction: ComponentInteraction) -> InteractionMessageBuilder: return ( interaction .build_response(ResponseType.MESSAGE_UPDATE) .add_embed(Embed(description="Hi there")) .set_content("Konnichiwa") ) ``` Returns ------- hikari.api.special_endpoints.InteractionMessageBuilder Interaction message response builder object. """ if type_ not in _IMMEDIATE_TYPES: raise ValueError("Invalid type passed for an immediate response") return self.app.rest.interaction_message_builder(type_) def build_deferred_response(self, type_: _DeferredTypesT, /) -> special_endpoints.InteractionDeferredBuilder: """Get a deferred message response builder for use in the REST server flow. !!! note For interactions received over the gateway `ComponentInteraction.create_initial_response` should be used to set the interaction response message. !!! note Unlike `hikari.api.special_endpoints.InteractionMessageBuilder`, the result of this call can be returned as is without any modifications being made to it. Parameters ---------- type_ : typing.Union[builtins.int, hikari.interactions.base_interactions.ResponseType] The type of deferred response this should be. This may be one of the following: * `hikari.interactions.base_interactions.ResponseType.DEFERRED_MESSAGE_CREATE` * `hikari.interactions.base_interactions.ResponseType.DEFERRED_MESSAGE_UPDATE` Returns ------- hikari.api.special_endpoints.InteractionDeferredBuilder Deferred interaction message response builder object. """ if type_ not in _DEFERRED_TYPES: raise ValueError("Invalid type passed for a deferred response") return self.app.rest.interaction_deferred_builder(type_) async def fetch_channel(self) -> channels.TextableChannel: """Fetch the channel this interaction occurred in. Returns ------- hikari.channels.TextableChannel The channel. This will be a _derivative_ of `hikari.channels.TextableChannel`. Raises ------ hikari.errors.UnauthorizedError If you are unauthorized to make the request (invalid/missing token). hikari.errors.ForbiddenError If you are missing the `READ_MESSAGES` permission in the channel. hikari.errors.NotFoundError If the channel 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.RateLimitTooLongError Raised in the event that a rate limit occurs that is longer than `max_rate_limit` when making a request. hikari.errors.RateLimitedError Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur. hikari.errors.InternalServerError If an internal error occurs on Discord while handling the request. """ channel = await self.app.rest.fetch_channel(self.channel_id) assert isinstance(channel, channels.TextableChannel) return channel def get_channel(self) -> typing.Union[channels.GuildTextChannel, channels.GuildNewsChannel, None]: """Get the guild channel this interaction occurred in. !!! note This will always return `builtins.None` for interactions triggered in a DM channel. Returns ------- typing.Union[hikari.channels.GuildTextChannel, hikari.channels.GuildNewsChannel, builtins.None] The object of the guild channel that was found in the cache or `builtins.None`. """ if isinstance(self.app, traits.CacheAware): channel = self.app.cache.get_guild_channel(self.channel_id) assert isinstance(channel, (channels.GuildTextChannel, channels.GuildNewsChannel)) return channel return None async def fetch_guild(self) -> typing.Optional[guilds.RESTGuild]: """Fetch the guild this interaction happened in. Returns ------- typing.Optional[hikari.guilds.RESTGuild] Object of the guild this interaction happened in or `builtins.None` if this occurred within a DM channel. Raises ------ hikari.errors.ForbiddenError If you are not part of the guild. hikari.errors.NotFoundError If the guild is not found. hikari.errors.UnauthorizedError If you are unauthorized to make the request (invalid/missing token). hikari.errors.RateLimitTooLongError Raised in the event that a rate limit occurs that is longer than `max_rate_limit` when making a request. hikari.errors.RateLimitedError Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur. hikari.errors.InternalServerError If an internal error occurs on Discord while handling the request. """ if not self.guild_id: return None return await self.app.rest.fetch_guild(self.guild_id) def get_guild(self) -> typing.Optional[guilds.GatewayGuild]: """Get the object of this interaction's guild guild from the cache. Returns ------- typing.Optional[hikari.guilds.GatewayGuild] The object of the guild if found, else `builtins.None`. """ if self.guild_id and isinstance(self.app, traits.CacheAware): return self.app.cache.get_guild(self.guild_id) return None async def fetch_parent_message(self) -> messages.Message: """Fetch the message which this interaction was triggered on. Returns ------- hikari.messages.Message The requested message. Raises ------ builtins.ValueError If `token` is not available. hikari.errors.UnauthorizedError If you are unauthorized to make the request (invalid/missing token). hikari.errors.NotFoundError If the webhook is not found or the webhook's message wasn't found. hikari.errors.RateLimitTooLongError Raised in the event that a rate limit occurs that is longer than `max_rate_limit` when making a request. hikari.errors.RateLimitedError Usually, Hikari will handle and retry on hitting rate-limits automatically. This includes most bucket-specific rate-limits and global rate-limits. In some rare edge cases, however, Discord implements other undocumented rules for rate-limiting, such as limits per attribute. These cannot be detected or handled normally by Hikari due to their undocumented nature, and will trigger this exception if they occur. hikari.errors.InternalServerError If an internal error occurs on Discord while handling the request. """ return await self.fetch_message(self.message.id) def get_parent_message(self) -> typing.Optional[messages.PartialMessage]: """Get the message which this interaction was triggered on from the cache. Returns ------- typing.Optional[hikari.messages.Message] The object of the message found in the cache or `builtins.None`. """ if isinstance(self.app, traits.CacheAware): return self.app.cache.get_message(self.message.id) return None
class VoiceStateData(BaseData[voices.VoiceState]): """A data model for storing voice state data in an in-memory cache.""" channel_id: typing.Optional[snowflakes.Snowflake] = attr.field() guild_id: snowflakes.Snowflake = attr.field() is_guild_deafened: bool = attr.field() is_guild_muted: bool = attr.field() is_self_deafened: bool = attr.field() is_self_muted: bool = attr.field() is_streaming: bool = attr.field() is_suppressed: bool = attr.field() is_video_enabled: bool = attr.field() member: RefCell[MemberData] = attr.field() session_id: str = attr.field() requested_to_speak_at: typing.Optional[datetime.datetime] = attr.field() def build_entity(self, app: traits.RESTAware, /) -> voices.VoiceState: member = self.member.object.build_entity(app) return voices.VoiceState( channel_id=self.channel_id, guild_id=self.guild_id, is_guild_deafened=self.is_guild_deafened, is_guild_muted=self.is_guild_muted, is_self_deafened=self.is_self_deafened, is_self_muted=self.is_self_muted, is_streaming=self.is_streaming, is_suppressed=self.is_suppressed, is_video_enabled=self.is_video_enabled, user_id=member.user.id, session_id=self.session_id, app=app, member=member, requested_to_speak_at=self.requested_to_speak_at, ) @classmethod def build_from_entity( cls, voice_state: voices.VoiceState, /, *, member: typing.Optional[RefCell[MemberData]] = None, ) -> VoiceStateData: return cls( channel_id=voice_state.channel_id, guild_id=voice_state.guild_id, is_self_deafened=voice_state.is_self_deafened, is_self_muted=voice_state.is_self_muted, is_guild_deafened=voice_state.is_guild_deafened, is_guild_muted=voice_state.is_guild_muted, is_streaming=voice_state.is_streaming, is_suppressed=voice_state.is_suppressed, is_video_enabled=voice_state.is_video_enabled, member=member or RefCell(MemberData.build_from_entity(voice_state.member)), session_id=voice_state.session_id, requested_to_speak_at=voice_state.requested_to_speak_at, )