Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Invite.type #1142

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions changelog/1141.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Support fetching invites with ``null`` channel (e.g. friend invites).
1 change: 1 addition & 0 deletions changelog/1141.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add :attr:`Invite.type`.
2 changes: 2 additions & 0 deletions disnake/audit_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,8 @@ def _convert_target_invite(self, target_id: int) -> Invite:
"code": changeset.code,
"temporary": changeset.temporary,
"uses": changeset.uses,
"type": 0,
"channel": None,
}

obj = Invite(state=self._state, data=fake_payload, guild=self.guild, channel=changeset.channel) # type: ignore
Expand Down
7 changes: 7 additions & 0 deletions disnake/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"ExpireBehavior",
"StickerType",
"StickerFormatType",
"InviteType",
"InviteTarget",
"VideoQualityMode",
"ComponentType",
Expand Down Expand Up @@ -599,6 +600,12 @@ def file_extension(self) -> str:
}


class InviteType(Enum):
guild = 0
group_dm = 1
friend = 2


class InviteTarget(Enum):
unknown = 0
stream = 1
Expand Down
1 change: 1 addition & 0 deletions disnake/guild.py
Original file line number Diff line number Diff line change
Expand Up @@ -3921,6 +3921,7 @@ async def vanity_invite(self, *, use_cached: bool = False) -> Optional[Invite]:
payload["max_uses"] = 0
payload["max_age"] = 0
payload["uses"] = payload.get("uses", 0)
payload["type"] = 0
return Invite(state=self._state, data=payload, guild=self, channel=channel)

# TODO: use MISSING when async iterators get refactored
Expand Down
40 changes: 24 additions & 16 deletions disnake/invite.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from .appinfo import PartialAppInfo
from .asset import Asset
from .enums import ChannelType, InviteTarget, NSFWLevel, VerificationLevel, try_enum
from .enums import ChannelType, InviteTarget, InviteType, NSFWLevel, VerificationLevel, try_enum
from .guild_scheduled_event import GuildScheduledEvent
from .mixins import Hashable
from .object import Object
Expand Down Expand Up @@ -307,8 +307,13 @@ class Invite(Hashable):
----------
code: :class:`str`
The URL fragment used for the invite.
type: :class:`InviteType`
The type of the invite.

.. versionadded:: 2.10

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.
The guild the invite is for. Can be ``None`` if it's not a guild invite (see :attr:`type`).
max_age: Optional[:class:`int`]
How long before the invite expires in seconds.
A value of ``0`` indicates that it doesn't expire.
Expand Down Expand Up @@ -382,6 +387,7 @@ class Invite(Hashable):
__slots__ = (
"max_age",
"code",
"type",
"guild",
"created_at",
"uses",
Expand Down Expand Up @@ -412,6 +418,7 @@ def __init__(
) -> None:
self._state: ConnectionState = state
self.code: str = data["code"]
self.type: InviteType = try_enum(InviteType, data.get("type", 0))
self.guild: Optional[InviteGuildType] = self._resolve_guild(data.get("guild"), guild)

self.max_age: Optional[int] = data.get("max_age")
Expand Down Expand Up @@ -481,15 +488,12 @@ def from_incomplete(cls, *, state: ConnectionState, data: InvitePayload) -> Self
# If it's not cached, then it has to be a partial guild
guild = PartialInviteGuild(state, guild_data, guild_id)

# todo: this is no longer true
# As far as I know, invites always need a channel
# So this should never raise.
channel: Union[PartialInviteChannel, GuildChannel] = PartialInviteChannel(
data=data["channel"], state=state
)
if guild is not None and not isinstance(guild, PartialInviteGuild):
# Upgrade the partial data if applicable
channel = guild.get_channel(channel.id) or channel
channel: Optional[Union[PartialInviteChannel, GuildChannel]] = None
if channel_data := data.get("channel"):
channel = PartialInviteChannel(data=channel_data, state=state)
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)

Expand Down Expand Up @@ -543,11 +547,15 @@ 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}>"
)
s = f"<Invite code={self.code!r} type={self.type!r}"
if self.type is not InviteType.friend:
shiftinv marked this conversation as resolved.
Show resolved Hide resolved
s += (
f" guild={self.guild!r}"
f" online={self.approximate_presence_count}"
f" members={self.approximate_member_count}"
)
s += ">"
return s

def __hash__(self) -> int:
return hash(self.code)
Expand Down
3 changes: 2 additions & 1 deletion disnake/types/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from .guild_scheduled_event import GuildScheduledEvent
from .integration import BaseIntegration
from .interactions import BaseInteraction, GuildApplicationCommandPermissions
from .invite import InviteTargetType
from .invite import InviteTargetType, InviteType
from .member import MemberWithUser
from .message import Message
from .role import Role
Expand Down Expand Up @@ -347,6 +347,7 @@ class InviteCreateEvent(TypedDict):
target_user: NotRequired[User]
target_application: NotRequired[PartialAppInfo]
temporary: bool
type: InviteType
uses: int # always 0


Expand Down
2 changes: 2 additions & 0 deletions disnake/types/invite.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from .guild_scheduled_event import GuildScheduledEvent
from .user import PartialUser

InviteType = Literal[0, 1, 2]
InviteTargetType = Literal[1, 2]


Expand All @@ -30,6 +31,7 @@ class _InviteMetadata(TypedDict, total=False):

class Invite(_InviteMetadata):
code: str
type: InviteType
guild: NotRequired[InviteGuild]
channel: InviteChannel
inviter: NotRequired[PartialUser]
Expand Down
21 changes: 21 additions & 0 deletions docs/api/invites.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,27 @@ PartialInviteChannel
Enumerations
------------

InviteType
~~~~~~~~~~

.. class:: InviteType

Represents the type of an invite.

.. versionadded:: 2.10

.. attribute:: guild

Represents an invite to a guild.

.. attribute:: group_dm

Represents an invite to a group channel.

.. attribute:: friend

Represents a friend invite.

InviteTarget
~~~~~~~~~~~~

Expand Down
Loading