Skip to content
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,16 @@ These changes are available on the `master` branch, but have not yet been releas

### Changed

- Inline `_InviteMetadata` fields into `IncompleteInvite` and remove the now-unused
`_InviteMetadata` TypedDict.
([#3313](https://github.com/Pycord-Development/pycord/pull/3313))

### Fixed

- Fix `Invite.code` handling when `None` (from `VanityInvitePayload`). `__str__` falls
back to `""`, `.url` and all code-dependent methods raise `ValueError`, and
`Invite.code` is typed as `str | None`.
([#3313](https://github.com/Pycord-Development/pycord/pull/3313))
- Fix an attribute error in `RoleColours.is_holographic()` when `secondary` or
`tertiary` is `None`.
([#3268](https://github.com/Pycord-Development/pycord/pull/3268))
Expand Down
31 changes: 27 additions & 4 deletions discord/invite.py
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ def __init__(
):
self._state: ConnectionState = state
self.max_age: int | None = data.get("max_age")
self.code: str = data["code"]
self.code: str | None = data.get("code")
self.guild: InviteGuildType | None = self._resolve_guild(
data.get("guild"), guild
)
Expand Down Expand Up @@ -689,7 +689,7 @@ def _resolve_roles(
return [Object(role_id) for role_id in role_ids]

def __str__(self) -> str:
return self.url
return self.code or ""

def __repr__(self) -> str:
return (
Expand All @@ -705,21 +705,30 @@ def __hash__(self) -> int:
return hash(self.code)

@property
def id(self) -> str:
def id(self) -> str: # type: ignore[override]
"""Returns the proper code portion of the invite."""
return self.code
return self.code or ""

@property
def url(self) -> str:
"""A property that retrieves the invite URL."""
if self.code is None:
raise ValueError("Cannot build an invite URL when code is None")
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

Raises
------
ValueError
The invite has no code.
"""
if self.code is None:
raise ValueError("Cannot manage target users for an invite with no code")
return InviteTargetUsers(invite_code=self.code, state=self._state)

async def edit_target_users(self, target_users_file: File) -> None:
Expand All @@ -738,13 +747,17 @@ async def edit_target_users(self, target_users_file: File) -> None:

Raises
------
ValueError
The invite has no code.
HTTPException
Updating the target users failed.
Forbidden
You do not have permissions to edit this invite.
NotFound
The invite is invalid or expired.
"""
if self.code is None:
raise ValueError("Cannot edit target users for an invite with no code")
await self._state.http.update_invite_target_users(
self.code, target_users_file=target_users_file
)
Expand All @@ -764,13 +777,19 @@ async def fetch_target_users_job_status(self) -> InviteTargetUsersJobStatus:

Raises
------
ValueError
The invite has no code.
HTTPException
Fetching the job status failed.
NotFound
The invite is invalid or expired.
Forbidden
You do not have permission to view the target users.
"""
if self.code is None:
raise ValueError(
"Cannot fetch target users job status for an invite with no code"
)
r = await self._state.http.get_invite_target_users_job_status(self.code)
return InviteTargetUsersJobStatus(data=r)

Expand All @@ -788,6 +807,8 @@ async def delete(self, *, reason: str | None = None):

Raises
------
ValueError
The invite has no code.
Forbidden
You do not have permissions to revoke invites.
NotFound
Expand All @@ -796,6 +817,8 @@ async def delete(self, *, reason: str | None = None):
Revoking the invite failed.
"""

if self.code is None:
raise ValueError("Cannot delete an invite with no code")
await self._state.http.delete_invite(self.code, reason=reason)

def set_scheduled_event(self, event: ScheduledEvent) -> None:
Expand Down
20 changes: 9 additions & 11 deletions discord/types/invite.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,20 @@
InviteTargetType = Literal[1, 2]


class _InviteMetadata(TypedDict, total=False):
uses: int
max_uses: int
max_age: int
temporary: bool
created_at: str
expires_at: str | None


class VanityInvite(_InviteMetadata):
class VanityInvite(TypedDict):
code: str | None
uses: int


class IncompleteInvite(_InviteMetadata):
class IncompleteInvite(TypedDict):
code: str
channel: PartialChannel
uses: NotRequired[int]
max_uses: NotRequired[int]
max_age: NotRequired[int]
temporary: NotRequired[bool]
created_at: NotRequired[str]
expires_at: NotRequired[str | None]


class Invite(IncompleteInvite):
Expand Down