On branch DiscordProfile
Initial commit
This commit is contained in:
@@ -0,0 +1,818 @@
|
||||
"""
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2021 Rapptz
|
||||
Copyright (c) 2021-present Pycord Development
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
import io
|
||||
import os
|
||||
from typing import TYPE_CHECKING, TypeVar, Union
|
||||
|
||||
from typing_extensions import override
|
||||
|
||||
from .appinfo import PartialAppInfo
|
||||
from .asset import Asset
|
||||
from .enums import (
|
||||
ChannelType,
|
||||
InviteTarget,
|
||||
InviteTargetUsersJobStatusCode,
|
||||
VerificationLevel,
|
||||
try_enum,
|
||||
)
|
||||
from .file import File
|
||||
from .mixins import Hashable
|
||||
from .object import Object
|
||||
from .role import Role
|
||||
from .utils import _get_as_snowflake, parse_time, snowflake_time
|
||||
|
||||
__all__ = (
|
||||
"PartialInviteChannel",
|
||||
"PartialInviteGuild",
|
||||
"Invite",
|
||||
"InviteTargetUsers",
|
||||
"InviteTargetUsersJobStatus",
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .abc import GuildChannel
|
||||
from .guild import Guild
|
||||
from .scheduled_events import ScheduledEvent
|
||||
from .state import ConnectionState
|
||||
from .types.channel import PartialChannel as InviteChannelPayload
|
||||
from .types.invite import GatewayInvite as GatewayInvitePayload
|
||||
from .types.invite import Invite as InvitePayload
|
||||
from .types.invite import InviteGuild as InviteGuildPayload
|
||||
from .types.invite import (
|
||||
InviteTargetUsersJobStatus as InviteTargetUsersJobStatusPayload,
|
||||
)
|
||||
from .types.invite import VanityInvite as VanityInvitePayload
|
||||
from .types.role import Role as RolePayload
|
||||
from .types.scheduled_events import ScheduledEvent as ScheduledEventPayload
|
||||
from .types.snowflake import Snowflake
|
||||
from .user import User
|
||||
|
||||
InviteGuildType = Union[Guild, "PartialInviteGuild", Object]
|
||||
InviteChannelType = Union[GuildChannel, "PartialInviteChannel", Object]
|
||||
|
||||
|
||||
class PartialInviteChannel:
|
||||
"""Represents a "partial" invite channel.
|
||||
|
||||
This model will be given when the user is not part of the
|
||||
guild the :class:`Invite` resolves to.
|
||||
|
||||
.. container:: operations
|
||||
|
||||
.. describe:: x == y
|
||||
|
||||
Checks if two partial channels are the same.
|
||||
|
||||
.. describe:: x != y
|
||||
|
||||
Checks if two partial channels are not the same.
|
||||
|
||||
.. describe:: hash(x)
|
||||
|
||||
Return the partial channel's hash.
|
||||
|
||||
.. describe:: str(x)
|
||||
|
||||
Returns the partial channel's name.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
name: :class:`str`
|
||||
The partial channel's name.
|
||||
id: :class:`int`
|
||||
The partial channel's ID.
|
||||
type: :class:`ChannelType`
|
||||
The partial channel's type.
|
||||
"""
|
||||
|
||||
__slots__ = ("id", "name", "type")
|
||||
|
||||
def __init__(self, data: InviteChannelPayload):
|
||||
self.id: int = int(data["id"])
|
||||
self.name: str = data["name"]
|
||||
self.type: ChannelType = try_enum(ChannelType, data["type"])
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return (
|
||||
f"<PartialInviteChannel id={self.id} name={self.name} type={self.type!r}>"
|
||||
)
|
||||
|
||||
@property
|
||||
def mention(self) -> str:
|
||||
"""The string that allows you to mention the channel."""
|
||||
return f"<#{self.id}>"
|
||||
|
||||
@property
|
||||
def created_at(self) -> datetime.datetime:
|
||||
"""Returns the channel's creation time in UTC."""
|
||||
return snowflake_time(self.id)
|
||||
|
||||
|
||||
class PartialInviteGuild:
|
||||
"""Represents a "partial" invite guild.
|
||||
|
||||
This model will be given when the user is not part of the
|
||||
guild the :class:`Invite` resolves to.
|
||||
|
||||
.. container:: operations
|
||||
|
||||
.. describe:: x == y
|
||||
|
||||
Checks if two partial guilds are the same.
|
||||
|
||||
.. describe:: x != y
|
||||
|
||||
Checks if two partial guilds are not the same.
|
||||
|
||||
.. describe:: hash(x)
|
||||
|
||||
Return the partial guild's hash.
|
||||
|
||||
.. describe:: str(x)
|
||||
|
||||
Returns the partial guild's name.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
name: :class:`str`
|
||||
The partial guild's name.
|
||||
id: :class:`int`
|
||||
The partial guild's ID.
|
||||
verification_level: :class:`VerificationLevel`
|
||||
The partial guild's verification level.
|
||||
features: List[:class:`str`]
|
||||
A list of features the guild has. See :attr:`Guild.features` for more information.
|
||||
description: Optional[:class:`str`]
|
||||
The partial guild's description.
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"_state",
|
||||
"features",
|
||||
"_icon",
|
||||
"_banner",
|
||||
"id",
|
||||
"name",
|
||||
"_splash",
|
||||
"verification_level",
|
||||
"description",
|
||||
)
|
||||
|
||||
def __init__(self, state: ConnectionState, data: InviteGuildPayload, id: int):
|
||||
self._state: ConnectionState = state
|
||||
self.id: int = id
|
||||
self.name: str = data["name"]
|
||||
self.features: list[str] = data.get("features", [])
|
||||
self._icon: str | None = data.get("icon")
|
||||
self._banner: str | None = data.get("banner")
|
||||
self._splash: str | None = data.get("splash")
|
||||
self.verification_level: VerificationLevel = try_enum(
|
||||
VerificationLevel, data.get("verification_level")
|
||||
)
|
||||
self.description: str | None = data.get("description")
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return (
|
||||
f"<{self.__class__.__name__} id={self.id} name={self.name!r} features={self.features} "
|
||||
f"description={self.description!r}>"
|
||||
)
|
||||
|
||||
@property
|
||||
def created_at(self) -> datetime.datetime:
|
||||
"""Returns the guild's creation time in UTC."""
|
||||
return snowflake_time(self.id)
|
||||
|
||||
@property
|
||||
def icon(self) -> Asset | None:
|
||||
"""Returns the guild's icon asset, if available."""
|
||||
if self._icon is None:
|
||||
return None
|
||||
return Asset._from_guild_icon(self._state, self.id, self._icon)
|
||||
|
||||
@property
|
||||
def banner(self) -> Asset | None:
|
||||
"""Returns the guild's banner asset, if available."""
|
||||
if self._banner is None:
|
||||
return None
|
||||
return Asset._from_guild_image(
|
||||
self._state, self.id, self._banner, path="banners"
|
||||
)
|
||||
|
||||
@property
|
||||
def splash(self) -> Asset | None:
|
||||
"""Returns the guild's invite splash asset, if available."""
|
||||
if self._splash is None:
|
||||
return None
|
||||
return Asset._from_guild_image(
|
||||
self._state, self.id, self._splash, path="splashes"
|
||||
)
|
||||
|
||||
|
||||
class InviteTargetUsersJobStatus:
|
||||
"""Represents the status of a target users processing job for an invite.
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
Attributes
|
||||
----------
|
||||
total_users: :class:`int`
|
||||
The total number of users to process.
|
||||
processed_users: :class:`int`
|
||||
The number of users that have been processed so far.
|
||||
created_at: Optional[:class:`datetime.datetime`]
|
||||
When the job was created. ``None`` if the creation time is not available.
|
||||
completed_at: Optional[:class:`datetime.datetime`]
|
||||
When the job was completed. ``None`` if the job is still processing.
|
||||
error_message: Optional[:class:`str`]
|
||||
The error message if the job failed. ``None`` if no error occurred.
|
||||
status: :class:`InviteTargetUsersJobStatusCode`
|
||||
The current status of the job.
|
||||
"""
|
||||
|
||||
def __init__(self, *, data: InviteTargetUsersJobStatusPayload):
|
||||
self.total_users: int = data["total_users"]
|
||||
self.processed_users: int = data["processed_users"]
|
||||
self.created_at: datetime.datetime | None = parse_time(data.get("created_at"))
|
||||
self.completed_at: datetime.datetime | None = parse_time(
|
||||
data.get("completed_at")
|
||||
)
|
||||
self.error_message: str | None = data.get("error_message")
|
||||
self.status: InviteTargetUsersJobStatusCode = try_enum(
|
||||
InviteTargetUsersJobStatusCode, data["status"]
|
||||
)
|
||||
|
||||
@override
|
||||
def __repr__(self) -> str:
|
||||
return (
|
||||
f"<InviteTargetUsersJobStatus total_users={self.total_users} processed_users={self.processed_users} "
|
||||
f"created_at={self.created_at!r} completed_at={self.completed_at!r} error_message={self.error_message} "
|
||||
f"status={self.status}>"
|
||||
)
|
||||
|
||||
|
||||
class InviteTargetUsers:
|
||||
"""
|
||||
Represents the target users CSV file for an invite.
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
Attributes
|
||||
----------
|
||||
invite_code: str
|
||||
The invite code for which the target users are associated.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
state: ConnectionState,
|
||||
invite_code: str,
|
||||
):
|
||||
self._state: ConnectionState = state
|
||||
self.invite_code: str = invite_code
|
||||
|
||||
async def read(self) -> bytes:
|
||||
"""|coro|
|
||||
|
||||
Retrieves this invite's target users CSV file as a :class:`bytes` object.
|
||||
|
||||
You must have created this invite or the :attr:`~Permissions.manage_guild` or :attr:`~Permissions.view_audit_log`
|
||||
permission to do this.
|
||||
|
||||
Returns
|
||||
-------
|
||||
:class:`bytes`
|
||||
The content of the CSV file.
|
||||
|
||||
Raises
|
||||
------
|
||||
DiscordException
|
||||
There was no internal connection state.
|
||||
HTTPException
|
||||
Downloading the file failed.
|
||||
NotFound
|
||||
This invite does not have any target users set.
|
||||
Forbidden
|
||||
You do not have permission to view the target users.
|
||||
"""
|
||||
return await self._state.http.get_invite_target_users(self.invite_code)
|
||||
|
||||
async def save(
|
||||
self,
|
||||
fp: str | bytes | os.PathLike[str] | io.BufferedIOBase,
|
||||
*,
|
||||
seek_begin: bool = True,
|
||||
) -> int:
|
||||
"""|coro|
|
||||
|
||||
Saves this invite's target users CSV file into a file-like object.
|
||||
|
||||
You must have created this invite or the :attr:`~Permissions.manage_guild` or :attr:`~Permissions.view_audit_log`
|
||||
permission to do this.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
fp: Union[:class:`io.BufferedIOBase`, :class:`os.PathLike`]
|
||||
The file-like object to save this file to or the filename
|
||||
to use. If a filename is passed then a file is created with that
|
||||
filename and used instead.
|
||||
seek_begin: :class:`bool`
|
||||
Whether to seek to the beginning of the file after saving is
|
||||
successfully done.
|
||||
|
||||
Returns
|
||||
-------
|
||||
:class:`int`
|
||||
The number of bytes written.
|
||||
|
||||
Raises
|
||||
------
|
||||
DiscordException
|
||||
There was no internal connection state.
|
||||
HTTPException
|
||||
Downloading the file failed.
|
||||
NotFound
|
||||
This invite does not have any target users set.
|
||||
Forbidden
|
||||
You do not have permission to view the target users.
|
||||
"""
|
||||
data = await self.read()
|
||||
if isinstance(fp, io.BufferedIOBase):
|
||||
written = fp.write(data)
|
||||
if seek_begin:
|
||||
fp.seek(0)
|
||||
return written
|
||||
else:
|
||||
with open(fp, "wb") as f:
|
||||
return f.write(data)
|
||||
|
||||
async def as_user_ids(self) -> list[int]:
|
||||
"""|coro|
|
||||
|
||||
Retrieves a list of user IDs that can accept this invite. This internally
|
||||
reads the invite's target users CSV file and parses the user IDs from it.
|
||||
|
||||
You must have created this invite or the :attr:`~Permissions.manage_guild` or :attr:`~Permissions.view_audit_log`
|
||||
permission to do this.
|
||||
|
||||
Returns
|
||||
-------
|
||||
list[int]
|
||||
A list of user IDs that can accept this invite.
|
||||
"""
|
||||
return [
|
||||
int(line.split(",")[0])
|
||||
for line in (await self.read())
|
||||
.decode()
|
||||
.splitlines()[1:] # first line is standardized "user_ids" header
|
||||
]
|
||||
|
||||
|
||||
I = TypeVar("I", bound="Invite")
|
||||
|
||||
|
||||
class Invite(Hashable):
|
||||
r"""Represents a Discord :class:`Guild` or :class:`abc.GuildChannel` invite.
|
||||
|
||||
Depending on the way this object was created, some of the attributes can
|
||||
have a value of ``None``.
|
||||
|
||||
.. container:: operations
|
||||
|
||||
.. describe:: x == y
|
||||
|
||||
Checks if two invites are equal.
|
||||
|
||||
.. describe:: x != y
|
||||
|
||||
Checks if two invites are not equal.
|
||||
|
||||
.. describe:: hash(x)
|
||||
|
||||
Returns the invite hash.
|
||||
|
||||
.. describe:: str(x)
|
||||
|
||||
Returns the invite URL.
|
||||
|
||||
The following table illustrates what methods will obtain the attributes:
|
||||
|
||||
+------------------------------------+------------------------------------------------------------+
|
||||
| Attribute | Method |
|
||||
+====================================+============================================================+
|
||||
| :attr:`max_age` | :meth:`abc.GuildChannel.invites`\, :meth:`Guild.invites` |
|
||||
+------------------------------------+------------------------------------------------------------+
|
||||
| :attr:`max_uses` | :meth:`abc.GuildChannel.invites`\, :meth:`Guild.invites` |
|
||||
+------------------------------------+------------------------------------------------------------+
|
||||
| :attr:`created_at` | :meth:`abc.GuildChannel.invites`\, :meth:`Guild.invites` |
|
||||
+------------------------------------+------------------------------------------------------------+
|
||||
| :attr:`temporary` | :meth:`abc.GuildChannel.invites`\, :meth:`Guild.invites` |
|
||||
+------------------------------------+------------------------------------------------------------+
|
||||
| :attr:`uses` | :meth:`abc.GuildChannel.invites`\, :meth:`Guild.invites` |
|
||||
+------------------------------------+------------------------------------------------------------+
|
||||
| :attr:`approximate_member_count` | :meth:`Client.fetch_invite` with `with_counts` enabled |
|
||||
+------------------------------------+------------------------------------------------------------+
|
||||
| :attr:`approximate_presence_count` | :meth:`Client.fetch_invite` with `with_counts` enabled |
|
||||
+------------------------------------+------------------------------------------------------------+
|
||||
| :attr:`expires_at` | :meth:`Client.fetch_invite` with `with_expiration` enabled |
|
||||
+------------------------------------+------------------------------------------------------------+
|
||||
|
||||
If it's not in the table above then it is available by all methods.
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
max_age: :class:`int`
|
||||
How long before the invite expires in seconds.
|
||||
A value of ``0`` indicates that it doesn't expire.
|
||||
code: :class:`str`
|
||||
The URL fragment used for the invite.
|
||||
guild: Optional[Union[:class:`Guild`, :class:`Object`, :class:`PartialInviteGuild`]]
|
||||
The guild the invite is for. Can be ``None`` if it's from a group direct message.
|
||||
revoked: :class:`bool`
|
||||
Indicates if the invite has been revoked.
|
||||
created_at: :class:`datetime.datetime`
|
||||
An aware UTC datetime object denoting the time the invite was created.
|
||||
temporary: :class:`bool`
|
||||
Indicates that the invite grants temporary membership.
|
||||
If ``True``, members who joined via this invite will be kicked upon disconnect.
|
||||
uses: :class:`int`
|
||||
How many times the invite has been used.
|
||||
max_uses: :class:`int`
|
||||
How many times the invite can be used.
|
||||
A value of ``0`` indicates that it has unlimited uses.
|
||||
inviter: Optional[:class:`User`]
|
||||
The user who created the invite.
|
||||
approximate_member_count: Optional[:class:`int`]
|
||||
The approximate number of members in the guild.
|
||||
approximate_presence_count: Optional[:class:`int`]
|
||||
The approximate number of members currently active in the guild.
|
||||
This includes idle, dnd, online, and invisible members. Offline members are excluded.
|
||||
expires_at: Optional[:class:`datetime.datetime`]
|
||||
The expiration date of the invite. If the value is ``None`` when received through
|
||||
`Client.fetch_invite` with `with_expiration` enabled, the invite will never expire.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
channel: Union[:class:`abc.GuildChannel`, :class:`Object`, :class:`PartialInviteChannel`]
|
||||
The channel the invite is for.
|
||||
target_type: :class:`InviteTarget`
|
||||
The type of target for the voice channel invite.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
target_user: Optional[:class:`User`]
|
||||
The user whose stream to display for this invite, if any.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
target_application: Optional[:class:`PartialAppInfo`]
|
||||
The embedded application the invite targets, if any.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
scheduled_event: Optional[:class:`ScheduledEvent`]
|
||||
The scheduled event linked with the invite.
|
||||
roles: List[Union[:class:`Role`, :class:`Object`]]
|
||||
The roles that will be assigned to a user that joins via this invite.
|
||||
|
||||
When using `Client.fetch_invite`, these may be partial role objects and have nullish attributes.
|
||||
|
||||
.. versionadded:: 2.8
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"max_age",
|
||||
"code",
|
||||
"guild",
|
||||
"revoked",
|
||||
"created_at",
|
||||
"uses",
|
||||
"temporary",
|
||||
"max_uses",
|
||||
"inviter",
|
||||
"channel",
|
||||
"target_user",
|
||||
"target_type",
|
||||
"_state",
|
||||
"approximate_member_count",
|
||||
"approximate_presence_count",
|
||||
"scheduled_event",
|
||||
"target_application",
|
||||
"expires_at",
|
||||
"roles",
|
||||
)
|
||||
|
||||
BASE = "https://discord.gg"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
state: ConnectionState,
|
||||
data: InvitePayload | VanityInvitePayload,
|
||||
guild: PartialInviteGuild | Guild | None = None,
|
||||
channel: PartialInviteChannel | GuildChannel | None = None,
|
||||
):
|
||||
self._state: ConnectionState = state
|
||||
self.max_age: int | None = data.get("max_age")
|
||||
self.code: str = data["code"]
|
||||
self.guild: InviteGuildType | None = self._resolve_guild(
|
||||
data.get("guild"), guild
|
||||
)
|
||||
self.revoked: bool | None = data.get("revoked")
|
||||
self.created_at: datetime.datetime | None = parse_time(data.get("created_at"))
|
||||
self.temporary: bool | None = data.get("temporary")
|
||||
self.uses: int | None = data.get("uses")
|
||||
self.max_uses: int | None = data.get("max_uses")
|
||||
self.approximate_presence_count: int | None = data.get(
|
||||
"approximate_presence_count"
|
||||
)
|
||||
self.approximate_member_count: int | None = data.get("approximate_member_count")
|
||||
|
||||
expires_at = data.get("expires_at", None)
|
||||
self.expires_at: datetime.datetime | None = (
|
||||
parse_time(expires_at) if expires_at else None
|
||||
)
|
||||
|
||||
inviter_data = data.get("inviter")
|
||||
self.inviter: User | None = (
|
||||
None if inviter_data is None else self._state.create_user(inviter_data)
|
||||
)
|
||||
|
||||
self.channel: InviteChannelType | None = self._resolve_channel(
|
||||
data.get("channel"), channel
|
||||
)
|
||||
|
||||
target_user_data = data.get("target_user")
|
||||
self.target_user: User | None = (
|
||||
None
|
||||
if target_user_data is None
|
||||
else self._state.create_user(target_user_data)
|
||||
)
|
||||
|
||||
self.target_type: InviteTarget = try_enum(
|
||||
InviteTarget, data.get("target_type", 0)
|
||||
)
|
||||
|
||||
from .scheduled_events import ScheduledEvent
|
||||
|
||||
scheduled_event: ScheduledEventPayload = data.get("guild_scheduled_event")
|
||||
self.scheduled_event: ScheduledEvent | None = (
|
||||
ScheduledEvent(state=state, data=scheduled_event)
|
||||
if scheduled_event
|
||||
else None
|
||||
)
|
||||
|
||||
application = data.get("target_application")
|
||||
self.target_application: PartialAppInfo | None = (
|
||||
PartialAppInfo(data=application, state=state) if application else None
|
||||
)
|
||||
|
||||
self.roles: list[Object | Role] = self._resolve_roles(
|
||||
role_ids=data.get("role_ids") or [], roles=data.get("roles") or []
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_incomplete(
|
||||
cls: type[I], *, state: ConnectionState, data: InvitePayload
|
||||
) -> I:
|
||||
guild: Guild | PartialInviteGuild | None
|
||||
try:
|
||||
guild_data = data["guild"]
|
||||
except KeyError:
|
||||
# If we're here, then this is a group DM
|
||||
guild = None
|
||||
else:
|
||||
guild_id = int(guild_data["id"])
|
||||
guild = state._get_guild(guild_id)
|
||||
if guild is None:
|
||||
# If it's not cached, then it has to be a partial guild
|
||||
guild = PartialInviteGuild(state, guild_data, guild_id)
|
||||
|
||||
# As far as I know, invites always need a channel
|
||||
# So this should never raise.
|
||||
channel: PartialInviteChannel | GuildChannel = PartialInviteChannel(
|
||||
data["channel"]
|
||||
)
|
||||
if guild is not None and not isinstance(guild, PartialInviteGuild):
|
||||
# Upgrade the partial data if applicable
|
||||
channel = guild.get_channel(channel.id) or channel
|
||||
|
||||
return cls(state=state, data=data, guild=guild, channel=channel)
|
||||
|
||||
@classmethod
|
||||
def from_gateway(
|
||||
cls: type[I], *, state: ConnectionState, data: GatewayInvitePayload
|
||||
) -> I:
|
||||
guild_id: int | None = _get_as_snowflake(data, "guild_id")
|
||||
guild: Guild | Object | None = state._get_guild(guild_id)
|
||||
channel_id = int(data["channel_id"])
|
||||
if guild is not None:
|
||||
channel = guild.get_channel(channel_id) or Object(id=channel_id) # type: ignore
|
||||
else:
|
||||
guild = Object(id=guild_id) if guild_id is not None else None
|
||||
channel = Object(id=channel_id)
|
||||
|
||||
return cls(state=state, data=data, guild=guild, channel=channel) # type: ignore
|
||||
|
||||
def _resolve_guild(
|
||||
self,
|
||||
data: InviteGuildPayload | None,
|
||||
guild: Guild | PartialInviteGuild | None = None,
|
||||
) -> InviteGuildType | None:
|
||||
if guild is not None:
|
||||
return guild
|
||||
|
||||
if data is None:
|
||||
return None
|
||||
|
||||
guild_id = int(data["id"])
|
||||
return PartialInviteGuild(self._state, data, guild_id)
|
||||
|
||||
def _resolve_channel(
|
||||
self,
|
||||
data: InviteChannelPayload | None,
|
||||
channel: PartialInviteChannel | GuildChannel | None = None,
|
||||
) -> InviteChannelType | None:
|
||||
if channel is not None:
|
||||
return channel
|
||||
|
||||
if data is None:
|
||||
return None
|
||||
|
||||
return PartialInviteChannel(data)
|
||||
|
||||
def _resolve_roles(
|
||||
self, role_ids: list[Snowflake], roles: list[RolePayload]
|
||||
) -> list[Object | Role]:
|
||||
if roles and self.guild is not None:
|
||||
result: list[Object | Role] = [
|
||||
Role(guild=self.guild, data=role, state=self._state) for role in roles
|
||||
]
|
||||
return result
|
||||
if self.guild is not None and not isinstance(self.guild, PartialInviteGuild):
|
||||
return [
|
||||
self.guild.get_role(int(role_id)) or Object(role_id)
|
||||
for role_id in role_ids
|
||||
]
|
||||
else:
|
||||
return [Object(role_id) for role_id in role_ids]
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.url
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return (
|
||||
f"<Invite code={self.code!r} guild={self.guild!r} "
|
||||
f"online={self.approximate_presence_count} "
|
||||
f"members={self.approximate_member_count} "
|
||||
f"scheduled_event={self.scheduled_event!r} "
|
||||
f"roles={self.roles!r}"
|
||||
f">"
|
||||
)
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(self.code)
|
||||
|
||||
@property
|
||||
def id(self) -> str:
|
||||
"""Returns the proper code portion of the invite."""
|
||||
return self.code
|
||||
|
||||
@property
|
||||
def url(self) -> str:
|
||||
"""A property that retrieves the invite URL."""
|
||||
return f"{self.BASE}/{self.code}{f'?event={self.scheduled_event.id}' if self.scheduled_event else ''}"
|
||||
|
||||
@property
|
||||
def target_users(self) -> InviteTargetUsers:
|
||||
"""An :class:`InviteTargetUsers` object for managing the target users list for this invite.
|
||||
|
||||
.. versionadded:: 2.8
|
||||
"""
|
||||
return InviteTargetUsers(invite_code=self.code, state=self._state)
|
||||
|
||||
async def edit_target_users(self, target_users_file: File) -> None:
|
||||
"""|coro|
|
||||
|
||||
Updates the target users list for this invite.
|
||||
|
||||
You must have created this invite or have the :attr:`~Permissions.manage_guild` permission to do this.
|
||||
|
||||
You can use :func:`utils.users_to_csv` to generate a virtual CSV file from a sequence of user IDs.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
target_users_file: :class:`File`
|
||||
A CSV file with a single column of user IDs for all the users able to accept this invite.
|
||||
|
||||
Raises
|
||||
------
|
||||
HTTPException
|
||||
Updating the target users failed.
|
||||
Forbidden
|
||||
You do not have permissions to edit this invite.
|
||||
NotFound
|
||||
The invite is invalid or expired.
|
||||
"""
|
||||
await self._state.http.update_invite_target_users(
|
||||
self.invite_code, target_users_file=target_users_file
|
||||
)
|
||||
|
||||
async def fetch_target_users_job_status(self) -> InviteTargetUsersJobStatus:
|
||||
"""|coro|
|
||||
|
||||
Retrieves the status of the target users processing job for this invite.
|
||||
|
||||
You must have created this invite or have the :attr:`~Permissions.manage_guild` or :attr:`~Permissions.view_audit_log` permissions.
|
||||
permission to do this.
|
||||
|
||||
Returns
|
||||
-------
|
||||
:class:`InviteTargetUsersJobStatus`
|
||||
The job status information.
|
||||
|
||||
Raises
|
||||
------
|
||||
HTTPException
|
||||
Fetching the job status failed.
|
||||
NotFound
|
||||
The invite is invalid or expired.
|
||||
Forbidden
|
||||
You do not have permission to view the target users.
|
||||
"""
|
||||
r = await self._state.http.get_invite_target_users_job_status(self.code)
|
||||
return InviteTargetUsersJobStatus(data=r)
|
||||
|
||||
async def delete(self, *, reason: str | None = None):
|
||||
"""|coro|
|
||||
|
||||
Revokes the instant invite.
|
||||
|
||||
You must have the :attr:`~Permissions.manage_channels` permission to do this.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
reason: Optional[:class:`str`]
|
||||
The reason for deleting this invite. Shows up on the audit log.
|
||||
|
||||
Raises
|
||||
------
|
||||
Forbidden
|
||||
You do not have permissions to revoke invites.
|
||||
NotFound
|
||||
The invite is invalid or expired.
|
||||
HTTPException
|
||||
Revoking the invite failed.
|
||||
"""
|
||||
|
||||
await self._state.http.delete_invite(self.code, reason=reason)
|
||||
|
||||
def set_scheduled_event(self, event: ScheduledEvent) -> None:
|
||||
"""Links the given scheduled event to this invite.
|
||||
|
||||
.. note::
|
||||
|
||||
Scheduled events aren't actually associated with invites on the API.
|
||||
Any guild channel invite can have an event attached to it. Using
|
||||
:meth:`abc.GuildChannel.create_invite`, :meth:`Client.fetch_invite`,
|
||||
or this method, you can link scheduled events.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
Parameters
|
||||
----------
|
||||
event: :class:`ScheduledEvent`
|
||||
The scheduled event object to link.
|
||||
"""
|
||||
self.scheduled_event = event
|
||||
Reference in New Issue
Block a user