aboutsummaryrefslogtreecommitdiff
path: root/discord
diff options
context:
space:
mode:
Diffstat (limited to 'discord')
-rw-r--r--discord/types/widget.py58
-rw-r--r--discord/user.py9
-rw-r--r--discord/widget.py104
3 files changed, 131 insertions, 40 deletions
diff --git a/discord/types/widget.py b/discord/types/widget.py
new file mode 100644
index 00000000..09081b86
--- /dev/null
+++ b/discord/types/widget.py
@@ -0,0 +1,58 @@
+"""
+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 typing import List, TypedDict
+from .activity import Activity
+from .snowflake import Snowflake
+from .user import User
+
+
+class WidgetChannel(TypedDict):
+ id: Snowflake
+ name: str
+ position: int
+
+
+class WidgetMember(User, total=False):
+ nick: str
+ game: Activity
+ status: str
+ avatar_url: str
+ deaf: bool
+ self_deaf: bool
+ mute: bool
+ self_mute: bool
+ suppress: bool
+
+
+class _WidgetOptional(TypedDict, total=False):
+ channels: List[WidgetChannel]
+ members: List[WidgetMember]
+ presence_count: int
+
+
+class Widget(_WidgetOptional):
+ id: Snowflake
+ name: str
+ instant_invite: str
diff --git a/discord/user.py b/discord/user.py
index 54d7a64e..95bcea25 100644
--- a/discord/user.py
+++ b/discord/user.py
@@ -22,6 +22,8 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
"""
+from typing import TYPE_CHECKING
+
import discord.abc
from .flags import PublicUserFlags
from .utils import snowflake_time, _bytes_to_base64_data
@@ -40,6 +42,13 @@ _BaseUser = discord.abc.User
class BaseUser(_BaseUser):
__slots__ = ('name', 'id', 'discriminator', '_avatar', 'bot', 'system', '_public_flags', '_state')
+ if TYPE_CHECKING:
+ name: str
+ id: int
+ discriminator: str
+ bot: bool
+ system: bool
+
def __init__(self, *, state, data):
self._state = state
self._update(data)
diff --git a/discord/widget.py b/discord/widget.py
index c09bfa98..c10b55cd 100644
--- a/discord/widget.py
+++ b/discord/widget.py
@@ -22,12 +22,24 @@ 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 Any, List, Optional, TYPE_CHECKING, Union
+
from .utils import snowflake_time, _get_as_snowflake, resolve_invite
from .user import BaseUser
-from .activity import create_activity
+from .activity import Activity, BaseActivity, Spotify, create_activity
from .invite import Invite
from .enums import Status, try_enum
+if TYPE_CHECKING:
+ import datetime
+ from .state import ConnectionState
+ from .types.widget import (
+ WidgetMember as WidgetMemberPayload,
+ Widget as WidgetPayload,
+ )
+
__all__ = (
'WidgetChannel',
'WidgetMember',
@@ -66,25 +78,24 @@ class WidgetChannel:
"""
__slots__ = ('id', 'name', 'position')
+ def __init__(self, id: int, name: str, position: int) -> None:
+ self.id: int = id
+ self.name: str = name
+ self.position: int = position
- def __init__(self, **kwargs):
- self.id = kwargs.pop('id')
- self.name = kwargs.pop('name')
- self.position = kwargs.pop('position')
-
- def __str__(self):
+ def __str__(self) -> str:
return self.name
- def __repr__(self):
+ def __repr__(self) -> str:
return f'<WidgetChannel id={self.id} name={self.name!r} position={self.position!r}>'
@property
- def mention(self):
+ def mention(self) -> str:
""":class:`str`: The string that allows you to mention the channel."""
return f'<#{self.id}>'
@property
- def created_at(self):
+ def created_at(self) -> datetime.datetime:
""":class:`datetime.datetime`: Returns the channel's creation time in UTC."""
return snowflake_time(self.id)
@@ -133,38 +144,49 @@ class WidgetMember(BaseUser):
Whether the member is currently muted.
suppress: Optional[:class:`bool`]
Whether the member is currently being suppressed.
- connected_channel: Optional[:class:`VoiceChannel`]
+ connected_channel: Optional[:class:`WidgetChannel`]
Which channel the member is connected to.
"""
__slots__ = ('name', 'status', 'nick', 'avatar', 'discriminator',
'id', 'bot', 'activity', 'deafened', 'suppress', 'muted',
'connected_channel')
- def __init__(self, *, state, data, connected_channel=None):
+ if TYPE_CHECKING:
+ activity: Optional[Union[BaseActivity, Spotify]]
+
+ def __init__(
+ self,
+ *,
+ state: ConnectionState,
+ data: WidgetMemberPayload,
+ connected_channel: Optional[WidgetChannel] = None
+ ) -> None:
super().__init__(state=state, data=data)
- self.nick = data.get('nick')
- self.status = try_enum(Status, data.get('status'))
- self.deafened = data.get('deaf', False) or data.get('self_deaf', False)
- self.muted = data.get('mute', False) or data.get('self_mute', False)
- self.suppress = data.get('suppress', False)
+ self.nick: Optional[str] = data.get('nick')
+ self.status: Status = try_enum(Status, data.get('status'))
+ self.deafened: Optional[bool] = data.get('deaf', False) or data.get('self_deaf', False)
+ self.muted: Optional[bool] = data.get('mute', False) or data.get('self_mute', False)
+ self.suppress: Optional[bool] = data.get('suppress', False)
try:
game = data['game']
except KeyError:
- self.activity = None
+ activity = None
else:
- self.activity = create_activity(game)
+ activity = create_activity(game)
+
+ self.activity: Optional[Union[BaseActivity, Spotify]] = activity
- self.connected_channel = connected_channel
+ self.connected_channel: Optional[WidgetChannel] = connected_channel
- def __repr__(self):
+ def __repr__(self) -> str:
return (
f"<WidgetMember name={self.name!r} discriminator={self.discriminator!r}"
f" bot={self.bot} nick={self.nick!r}>"
)
@property
- def display_name(self):
+ def display_name(self) -> str:
""":class:`str`: Returns the member's display name."""
return self.nick or self.name
@@ -191,9 +213,9 @@ class Widget:
The guild's ID.
name: :class:`str`
The guild's name.
- channels: Optional[List[:class:`WidgetChannel`]]
+ channels: List[:class:`WidgetChannel`]
The accessible voice channels in the guild.
- members: Optional[List[:class:`Member`]]
+ members: List[:class:`Member`]
The online members in the server. Offline members
do not appear in the widget.
@@ -207,53 +229,55 @@ class Widget:
"""
__slots__ = ('_state', 'channels', '_invite', 'id', 'members', 'name')
- def __init__(self, *, state, data):
+ def __init__(self, *, state: ConnectionState, data: WidgetPayload) -> None:
self._state = state
self._invite = data['instant_invite']
- self.name = data['name']
- self.id = int(data['id'])
+ self.name: str = data['name']
+ self.id: int = int(data['id'])
- self.channels = []
+ self.channels: List[WidgetChannel] = []
for channel in data.get('channels', []):
_id = int(channel['id'])
self.channels.append(WidgetChannel(id=_id, name=channel['name'], position=channel['position']))
- self.members = []
+ self.members: List[WidgetMember] = []
channels = {channel.id: channel for channel in self.channels}
for member in data.get('members', []):
connected_channel = _get_as_snowflake(member, 'channel_id')
if connected_channel in channels:
- connected_channel = channels[connected_channel]
+ connected_channel = channels[connected_channel] # type: ignore
elif connected_channel:
connected_channel = WidgetChannel(id=connected_channel, name='', position=0)
- self.members.append(WidgetMember(state=self._state, data=member, connected_channel=connected_channel))
+ self.members.append(WidgetMember(state=self._state, data=member, connected_channel=connected_channel)) # type: ignore
- def __str__(self):
+ def __str__(self) -> str:
return self.json_url
- def __eq__(self, other):
- return self.id == other.id
+ def __eq__(self, other: Any) -> bool:
+ if isinstance(other, Widget):
+ return self.id == other.id
+ return False
- def __repr__(self):
+ def __repr__(self) -> str:
return f'<Widget id={self.id} name={self.name!r} invite_url={self.invite_url!r}>'
@property
- def created_at(self):
+ def created_at(self) -> datetime.datetime:
""":class:`datetime.datetime`: Returns the member's creation time in UTC."""
return snowflake_time(self.id)
@property
- def json_url(self):
+ def json_url(self) -> str:
""":class:`str`: The JSON URL of the widget."""
return f"https://discord.com/api/guilds/{self.id}/widget.json"
@property
- def invite_url(self):
+ def invite_url(self) -> str:
"""Optional[:class:`str`]: The invite URL for the guild, if available."""
return self._invite
- async def fetch_invite(self, *, with_counts=True):
+ async def fetch_invite(self, *, with_counts: bool = True) -> Optional[Invite]:
"""|coro|
Retrieves an :class:`Invite` from a invite URL or ID.
@@ -269,7 +293,7 @@ class Widget:
Returns
--------
- :class:`Invite`
+ Optional[:class:`Invite`]
The invite from the URL/ID.
"""
if self._invite: