aboutsummaryrefslogtreecommitdiff
path: root/discord
diff options
context:
space:
mode:
Diffstat (limited to 'discord')
-rw-r--r--discord/abc.py21
-rw-r--r--discord/appinfo.py83
-rw-r--r--discord/enums.py2
-rw-r--r--discord/http.py12
-rw-r--r--discord/invite.py20
-rw-r--r--discord/team.py22
-rw-r--r--discord/types/appinfo.py66
-rw-r--r--discord/types/invite.py6
-rw-r--r--discord/types/team.py43
9 files changed, 251 insertions, 24 deletions
diff --git a/discord/abc.py b/discord/abc.py
index 961545ed..da1636f2 100644
--- a/discord/abc.py
+++ b/discord/abc.py
@@ -62,6 +62,7 @@ if TYPE_CHECKING:
from .channel import CategoryChannel
from .embeds import Embed
from .message import Message, MessageReference
+ from .enums import InviteTarget
SnowflakeTime = Union["Snowflake", datetime]
@@ -1013,6 +1014,9 @@ class GuildChannel:
max_uses: int = 0,
temporary: bool = False,
unique: bool = True,
+ target_type: Optional[InviteTarget] = None,
+ target_user: Optional[User] = None,
+ target_application_id: Optional[int] = None
) -> Invite:
"""|coro|
@@ -1038,6 +1042,20 @@ class GuildChannel:
invite.
reason: Optional[:class:`str`]
The reason for creating this invite. Shows up on the audit log.
+ target_type: Optional[:class:`InviteTarget`]
+ The type of target for the voice channel invite, if any.
+
+ .. versionadded:: 2.0
+
+ target_user: Optional[:class:`User`]
+ The user whose stream to display for this invite, required if `target_type` is `TargetType.stream`. The user must be streaming in the channel.
+
+ .. versionadded:: 2.0
+
+ target_application_id:: Optional[:class:`int`]
+ The id of the embedded application for the invite, required if `target_type` is `TargetType.embedded_application`.
+
+ .. versionadded:: 2.0
Raises
-------
@@ -1060,6 +1078,9 @@ class GuildChannel:
max_uses=max_uses,
temporary=temporary,
unique=unique,
+ target_type=target_type.value if target_type else None,
+ target_user_id=target_user.id if target_user else None,
+ target_application_id=target_application_id
)
return Invite.from_incomplete(data=data, state=self._state)
diff --git a/discord/appinfo.py b/discord/appinfo.py
index 40a4e402..a7f8da82 100644
--- a/discord/appinfo.py
+++ b/discord/appinfo.py
@@ -22,13 +22,22 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
"""
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Optional
+
from . import utils
-from .user import User
from .asset import Asset
-from .team import Team
+
+if TYPE_CHECKING:
+ from .guild import Guild
+ from .types.appinfo import AppInfo as AppInfoPayload, PartialAppInfo as PartialAppInfoPayload
+
+ from .state import ConnectionState
__all__ = (
'AppInfo',
+ 'PartialAppInfo',
)
@@ -49,7 +58,7 @@ class AppInfo:
.. versionadded:: 1.3
- description: Optional[:class:`str`]
+ description: :class:`str`
The application description.
bot_public: :class:`bool`
Whether the bot can be invited by anyone or if it is locked
@@ -122,9 +131,10 @@ class AppInfo:
'privacy_policy_url',
)
- def __init__(self, state, data):
- self._state = state
+ def __init__(self, state, data: AppInfoPayload):
+ from .team import Team
+ self._state = state
self.id = int(data['id'])
self.name = data['name']
self.description = data['description']
@@ -132,7 +142,7 @@ class AppInfo:
self.rpc_origins = data['rpc_origins']
self.bot_public = data['bot_public']
self.bot_require_code_grant = data['bot_require_code_grant']
- self.owner = User(state=self._state, data=data['owner'])
+ self.owner = state.store_user(data['owner'])
team = data.get('team')
self.team = Team(state, team) if team else None
@@ -148,7 +158,7 @@ class AppInfo:
self.terms_of_service_url = data.get('terms_of_service_url')
self.privacy_policy_url = data.get('privacy_policy_url')
- def __repr__(self):
+ def __repr__(self) -> str:
return (
f'<{self.__class__.__name__} id={self.id} name={self.name!r} '
f'description={self.description!r} public={self.bot_public} '
@@ -156,14 +166,14 @@ class AppInfo:
)
@property
- def icon(self):
+ def icon(self) -> Optional[Asset]:
"""Optional[:class:`.Asset`]: Retrieves the application's icon asset, if any."""
if self._icon is None:
return None
return Asset._from_icon(self._state, self.id, self._icon, path='app')
@property
- def cover_image(self):
+ def cover_image(self) -> Optional[Asset]:
"""Optional[:class:`.Asset`]: Retrieves the cover image on a store embed, if any.
This is only available if the application is a game sold on Discord.
@@ -173,10 +183,61 @@ class AppInfo:
return Asset._from_cover_image(self._state, self.id, self._cover_image)
@property
- def guild(self):
+ def guild(self) -> Optional[Guild]:
"""Optional[:class:`Guild`]: If this application is a game sold on Discord,
this field will be the guild to which it has been linked
.. versionadded:: 1.3
"""
- return self._state._get_guild(int(self.guild_id))
+ return self._state._get_guild(self.guild_id)
+
+class PartialAppInfo:
+ """Represents a partial AppInfo given by :func:`~GuildChannel.create_invite`
+
+ .. versionadded:: 2.0
+
+ Attributes
+ -------------
+ id: :class:`int`
+ The application ID.
+ name: :class:`str`
+ The application name.
+ description: :class:`str`
+ The application description.
+ rpc_origins: Optional[List[:class:`str`]]
+ A list of RPC origin URLs, if RPC is enabled.
+ summary: :class:`str`
+ If this application is a game sold on Discord,
+ this field will be the summary field for the store page of its primary SKU.
+ verify_key: :class:`str`
+ The hex encoded key for verification in interactions and the
+ GameSDK's `GetTicket <https://discord.com/developers/docs/game-sdk/applications#getticket>`_.
+ terms_of_service_url: Optional[:class:`str`]
+ The application's terms of service URL, if set.
+ privacy_policy_url: Optional[:class:`str`]
+ The application's privacy policy URL, if set.
+ """
+
+ __slots__ = ('_state', 'id', 'name', 'description', 'rpc_origins', 'summary', 'verify_key', 'terms_of_service_url', 'privacy_policy_url', '_icon')
+
+ def __init__(self, *, state: ConnectionState, data: PartialAppInfoPayload):
+ self._state = state
+ self.id = int(data['id'])
+ self.name = data['name']
+ self._icon = data.get('icon')
+ self.description = data['description']
+ self.rpc_origins = data.get('rpc_origins')
+ self.summary = data['summary']
+ self.verify_key = data['verify_key']
+ self.terms_of_service_url = data.get('terms_of_service_url')
+ self.privacy_policy_url = data.get('privacy_policy_url')
+
+ def __repr__(self) -> str:
+ return f'<{self.__class__.__name__} id={self.id} name={self.name!r} description={self.description!r}>'
+
+ @property
+ def icon(self) -> Optional[Asset]:
+ """Optional[:class:`.Asset`]: Retrieves the application's icon asset, if any."""
+ if self._icon is None:
+ return None
+ return Asset._from_icon(self._state, self.id, self._icon, path='app')
diff --git a/discord/enums.py b/discord/enums.py
index fa86767d..aaa59b25 100644
--- a/discord/enums.py
+++ b/discord/enums.py
@@ -431,7 +431,7 @@ class StickerType(Enum):
class InviteTarget(Enum):
unknown = 0
- stream = 1
+ stream = 1
embedded_application = 2
class InteractionType(Enum):
diff --git a/discord/http.py b/discord/http.py
index 67529495..c14cc8d4 100644
--- a/discord/http.py
+++ b/discord/http.py
@@ -981,6 +981,9 @@ class HTTPClient:
max_uses: int = 0,
temporary: bool = False,
unique: bool = True,
+ target_type: Optional[int] = None,
+ target_user_id: Optional[int] = None,
+ target_application_id: Optional[int] = None
) -> Response[invite.Invite]:
r = Route('POST', '/channels/{channel_id}/invites', channel_id=channel_id)
payload = {
@@ -990,6 +993,15 @@ class HTTPClient:
'unique': unique,
}
+ if target_type:
+ payload['target_type'] = target_type
+
+ if target_user_id:
+ payload['target_user_id'] = target_user_id
+
+ if target_application_id:
+ payload['target_application_id'] = str(target_application_id)
+
return self.request(r, reason=reason, json=payload)
def get_invite(self, invite_id, *, with_counts=True, with_expiration=True):
diff --git a/discord/invite.py b/discord/invite.py
index 213ef5a4..8e60d1e8 100644
--- a/discord/invite.py
+++ b/discord/invite.py
@@ -30,6 +30,7 @@ from .utils import parse_time, snowflake_time, _get_as_snowflake
from .object import Object
from .mixins import Hashable
from .enums import ChannelType, VerificationLevel, InviteTarget, try_enum
+from .appinfo import PartialAppInfo
__all__ = (
'PartialInviteChannel',
@@ -277,12 +278,18 @@ class Invite(Hashable):
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 target of this invite in the case of stream invites.
+ The user whose stream to display for this invite, if any.
.. versionadded:: 2.0
- target_type: :class:`InviteTarget`
- The invite's target type.
+
+ target_application: Optional[:class:`PartialAppInfo`]
+ The embedded application the invite targets, if any.
.. versionadded:: 2.0
"""
@@ -303,6 +310,7 @@ class Invite(Hashable):
'_state',
'approximate_member_count',
'approximate_presence_count',
+ 'target_application',
'expires_at',
)
@@ -328,7 +336,11 @@ class Invite(Hashable):
self.channel = data.get('channel')
target_user_data = data.get('target_user')
self.target_user = None if target_user_data is None else self._state.store_user(target_user_data)
- self.target_type = try_enum(InviteTarget, data.get('target_type', 0))
+
+ self.target_type = try_enum(InviteTarget, data.get("target_type", 0))
+
+ application = data.get('target_application')
+ self.target_application = PartialAppInfo(data=application, state=state) if application else None
@classmethod
def from_incomplete(cls, *, state, data):
diff --git a/discord/team.py b/discord/team.py
index 5e47770b..94cf6e59 100644
--- a/discord/team.py
+++ b/discord/team.py
@@ -22,11 +22,21 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
"""
+from __future__ import annotations
+
from . import utils
from .user import BaseUser
from .asset import Asset
from .enums import TeamMembershipState, try_enum
+from typing import TYPE_CHECKING, Optional
+
+if TYPE_CHECKING:
+ from .types.team import (
+ Team as TeamPayload,
+ TeamMember as TeamMemberPayload,
+ )
+
__all__ = (
'Team',
'TeamMember',
@@ -52,7 +62,7 @@ class Team:
__slots__ = ('_state', 'id', 'name', '_icon', 'owner_id', 'members')
- def __init__(self, state, data):
+ def __init__(self, state, data: TeamPayload):
self._state = state
self.id = int(data['id'])
@@ -61,18 +71,18 @@ class Team:
self.owner_id = utils._get_as_snowflake(data, 'owner_user_id')
self.members = [TeamMember(self, self._state, member) for member in data['members']]
- def __repr__(self):
+ def __repr__(self) -> str:
return f'<{self.__class__.__name__} id={self.id} name={self.name}>'
@property
- def icon(self):
+ def icon(self) -> Optional[Asset]:
"""Optional[:class:`.Asset`]: Retrieves the team's icon asset, if any."""
if self._icon is None:
return None
return Asset._from_icon(self._state, self.id, self._icon, path='team')
@property
- def owner(self):
+ def owner(self) -> Optional[TeamMember]:
"""Optional[:class:`TeamMember`]: The team's owner."""
return utils.get(self.members, id=self.owner_id)
@@ -120,13 +130,13 @@ class TeamMember(BaseUser):
__slots__ = BaseUser.__slots__ + ('team', 'membership_state', 'permissions')
- def __init__(self, team, state, data):
+ def __init__(self, team: Team, state, data: TeamMemberPayload):
self.team = team
self.membership_state = try_enum(TeamMembershipState, data['membership_state'])
self.permissions = data['permissions']
super().__init__(state=state, data=data['user'])
- def __repr__(self):
+ def __repr__(self) -> str:
return (
f'<{self.__class__.__name__} id={self.id} name={self.name!r} '
f'discriminator={self.discriminator!r} membership_state={self.membership_state!r}>'
diff --git a/discord/types/appinfo.py b/discord/types/appinfo.py
new file mode 100644
index 00000000..d223837f
--- /dev/null
+++ b/discord/types/appinfo.py
@@ -0,0 +1,66 @@
+"""
+The MIT License (MIT)
+
+Copyright (c) 2015-present Rapptz
+
+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
+
+from typing import TypedDict, List, Optional
+
+from .user import User
+from .team import Team
+from .snowflake import Snowflake
+
+class BaseAppInfo(TypedDict):
+ id: Snowflake
+ name: str
+ verify_key: str
+ icon: Optional[str]
+ summary: str
+ description: str
+
+class _AppInfoOptional(TypedDict, total=False):
+ team: Team
+ guild_id: Snowflake
+ primary_sku_id: Snowflake
+ slug: str
+ terms_of_service_url: str
+ privacy_policy_url: str
+ hook: bool
+ max_participants: int
+
+class AppInfo(BaseAppInfo, _AppInfoOptional):
+ rpc_origins: List[str]
+ owner: User
+ bot_public: bool
+ bot_require_code_grant: bool
+
+class _PartialAppInfoOptional(TypedDict, total=False):
+ rpc_origins: List[str]
+ cover_image: str
+ hook: bool
+ terms_of_service_url: str
+ privacy_policy_url: str
+ max_participants: int
+
+class PartialAppInfo(_PartialAppInfoOptional, BaseAppInfo):
+ pass
diff --git a/discord/types/invite.py b/discord/types/invite.py
index 25466158..3760f0fa 100644
--- a/discord/types/invite.py
+++ b/discord/types/invite.py
@@ -29,15 +29,17 @@ from typing import Literal, TypedDict
from .guild import InviteGuild, _GuildPreviewUnique
from .channel import PartialChannel
from .user import PartialUser
+from .appinfo import PartialAppInfo
-TargetUserType = Literal[1]
+InviteTargetType = Literal[1, 2]
class _InviteOptional(TypedDict, total=False):
guild: InviteGuild
inviter: PartialUser
target_user: PartialUser
- target_user_type: TargetUserType
+ target_type: InviteTargetType
+ target_application: PartialAppInfo
class _InviteMetadata(TypedDict, total=False):
diff --git a/discord/types/team.py b/discord/types/team.py
new file mode 100644
index 00000000..e8cd524f
--- /dev/null
+++ b/discord/types/team.py
@@ -0,0 +1,43 @@
+"""
+The MIT License (MIT)
+
+Copyright (c) 2015-present Rapptz
+
+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
+
+from typing import TypedDict, List
+
+from .user import PartialUser
+from .snowflake import Snowflake
+
+class TeamMember(TypedDict):
+ user: PartialUser
+ membership_state: int
+ permissions: List[str]
+ team_id: Snowflake
+
+class Team(TypedDict):
+ id: Snowflake
+ name: str
+ owner_id: Snowflake
+ members: List[TeamMember]
+ icon: str