aboutsummaryrefslogtreecommitdiff
path: root/discord/widget.py
diff options
context:
space:
mode:
authorNCPlayz <[email protected]>2019-03-15 19:39:15 +0000
committerRapptz <[email protected]>2019-03-19 09:22:48 -0400
commit8a30a4cac0651df5a24cb744fc104ced90a4cf3a (patch)
treef211cab296d0aa43a6df3aa7f55c3771d34909c9 /discord/widget.py
parentExpose Metadata (diff)
downloaddiscord.py-8a30a4cac0651df5a24cb744fc104ced90a4cf3a.tar.xz
discord.py-8a30a4cac0651df5a24cb744fc104ced90a4cf3a.zip
Add support for guild widget
Diffstat (limited to 'discord/widget.py')
-rw-r--r--discord/widget.py244
1 files changed, 244 insertions, 0 deletions
diff --git a/discord/widget.py b/discord/widget.py
new file mode 100644
index 00000000..7bb4f0a2
--- /dev/null
+++ b/discord/widget.py
@@ -0,0 +1,244 @@
+# -*- coding: utf-8 -*-
+
+"""
+The MIT License (MIT)
+
+Copyright (c) 2015-2019 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 .utils import snowflake_time, _get_as_snowflake, resolve_invite
+from .user import BaseUser
+from .activity import Activity
+from .invite import Invite
+from .enums import Status, try_enum
+from collections import namedtuple
+
+VALID_ICON_FORMATS = {"jpeg", "jpg", "webp", "png"}
+
+class WidgetChannel(namedtuple('WidgetChannel', 'id name position')):
+ """Represents a "partial" widget channel.
+
+ .. 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
+ -----------
+ id: :class:`int`
+ The channel's ID.
+ name: :class:`str`
+ The channel's name.
+ position: :class:`int`
+ The channel's position
+ """
+ __slots__ = ()
+
+ def __str__(self):
+ return self.name
+
+ @property
+ def mention(self):
+ """:class:`str`: The string that allows you to mention the channel."""
+ return '<#%s>' % self.id
+
+ @property
+ def created_at(self):
+ """Returns the channel's creation time in UTC."""
+ return snowflake_time(self.id)
+
+class WidgetMember(BaseUser):
+ """Represents a "partial" member of the widget's guild.
+
+ .. container:: operations
+
+ .. describe:: x == y
+
+ Checks if two widget members are the same.
+
+ .. describe:: x != y
+
+ Checks if two widget members are not the same.
+
+ .. describe:: hash(x)
+
+ Return the widget member's hash.
+
+ .. describe:: str(x)
+
+ Returns the widget member's `name#discriminator`.
+
+ Attributes
+ -----------
+ id: :class:`int`
+ The member's ID.
+ name: :class:`str`
+ The member's username.
+ discriminator: :class:`str`
+ The member's discriminator.
+ bot: :class:`bool`
+ Whether the member is a bot.
+ status: :class:`Status`
+ The member's status.
+ nick: Optional[:class:`str`]
+ The member's nickname.
+ avatar: Optional[:class:`str`]
+ The member's avatar hash.
+ activity: Optional[:class:`Activity`]
+ The member's activity.
+ deafened: Optional[:class:`bool`]
+ Whether the member is currently deafened.
+ muted: Optional[:class:`bool`]
+ Whether the member is currently muted.
+ suppress: Optional[:class:`bool`]
+ Whether the member is currently being suppressed.
+ connected_channel: Optional[:class:`VoiceChannel`]
+ 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):
+ 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)
+
+ game = data.get('game')
+ if game:
+ self.activity = Activity(**game)
+
+ self.connected_channel = connected_channel
+
+ @property
+ def display_name(self):
+ """:class:`str`: Returns the member's display name."""
+ return self.nick if self.nick else self.name
+
+class Widget:
+ """Represents a :class:`Guild` widget.
+
+ .. container:: operations
+
+ .. describe:: x == y
+
+ Checks if two widgets are the same.
+
+ .. describe:: x != y
+
+ Checks if two widgets are not the same.
+
+ .. describe:: str(x)
+
+ Returns the widget's JSON URL.
+
+ Attributes
+ -----------
+ id: :class:`int`
+ The guild's ID.
+ name: :class:`str`
+ The guild's name.
+ channels: Optional[List[:class:`WidgetChannel`]]
+ The accessible voice channels in the guild.
+ members: Optional[List[:class:`Member`]]
+ The online members in the server. Offline members
+ do not appear in the widget.
+ """
+ __slots__ = ('_state', 'channels', '_invite', 'id', 'members', 'name')
+
+ def __init__(self, *, state, data):
+ self._state = state
+ self._invite = data['instant_invite']
+ self.name = data['name']
+ self.id = int(data['id'])
+
+ self.channels = []
+ for channel in data.get('channels', []):
+ _id = int(channel['id'])
+ self.channels.append(WidgetChannel(id=_id, name=channel['name'], position=channel['position']))
+
+ self.members = []
+ 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:
+ connected_channel = channels[connected_channel]
+
+ self.members.append(WidgetMember(state=self._state, data=member, connected_channel=connected_channel))
+
+ def __str__(self):
+ return self.json_url
+
+ def __eq__(self, other):
+ return self.id == other.id
+
+ def __repr__(self):
+ return '<Widget id={0.id} name={0.name!r} invite={0.invite!r}>'.format(self)
+
+ @property
+ def created_at(self):
+ """Returns the member's creation time in UTC."""
+ return snowflake_time(self.id)
+
+ @property
+ def json_url(self):
+ """The JSON URL of the widget."""
+ return "https://discordapp.com/api/guilds/{0.id}/widget.json".format(self)
+
+ async def fetch_invite(self, *, with_counts=True):
+ """|coro|
+
+ Retrieves an :class:`Invite` from a invite URL or ID.
+ This is the same as :meth:`Client.get_invite`; the invite
+ code is abstracted away.
+
+ Parameters
+ -----------
+ with_counts: :class:`bool`
+ Whether to include count information in the invite. This fills the
+ :attr:`Invite.approximate_member_count` and :attr:`Invite.approximate_presence_count`
+ fields.
+
+ Returns
+ --------
+ :class:`Invite`
+ The invite from the URL/ID.
+ """
+ if self._invite:
+ invite_id = resolve_invite(self._invite)
+ data = await self._state.http.get_invite(invite_id, with_counts=with_counts)
+ return Invite.from_incomplete(state=self._state, data=data)