示例#1
0
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.
示例#2
0
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."""
示例#3
0
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.
示例#4
0
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})
示例#5
0
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
示例#6
0
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]
示例#7
0
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),
        )
示例#8
0
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)
示例#9
0
文件: files.py 项目: hikari-py/hikari
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
示例#10
0
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})
示例#11
0
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
示例#12
0
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
示例#13
0
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)
示例#14
0
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})
示例#15
0
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}"
示例#16
0
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,
        )
示例#17
0
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
示例#18
0
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
示例#19
0
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}
示例#20
0
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
示例#21
0
文件: files.py 项目: ashwinvin/hikari
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
示例#22
0
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],
        )
示例#23
0
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.
示例#24
0
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()
示例#25
0
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}"
示例#26
0
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()
示例#27
0
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
示例#28
0
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.
示例#29
0
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
示例#30
0
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,
        )