aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRapptz <[email protected]>2017-02-09 20:47:47 -0500
committerRapptz <[email protected]>2017-02-09 20:50:02 -0500
commitca81f0c3fcdd29b16adbf39c616ab15231d21a7f (patch)
treeaf1ca89e7e79e44b1a69333f3aa1658adf1b3f89
parentCall message edit handlers after attempting to patch individual fields (diff)
downloaddiscord.py-ca81f0c3fcdd29b16adbf39c616ab15231d21a7f.tar.xz
discord.py-ca81f0c3fcdd29b16adbf39c616ab15231d21a7f.zip
Better group DM support.
-rw-r--r--discord/channel.py105
-rw-r--r--discord/http.py31
-rw-r--r--discord/user.py39
3 files changed, 174 insertions, 1 deletions
diff --git a/discord/channel.py b/discord/channel.py
index 8699c25e..af11eea2 100644
--- a/discord/channel.py
+++ b/discord/channel.py
@@ -359,7 +359,6 @@ class GroupChannel(discord.abc.Messageable, Hashable):
def __init__(self, *, me, state, data):
self._state = state
- self.recipients = [state.store_user(u) for u in data['recipients']]
self.id = int(data['id'])
self.me = me
self._update_group(data)
@@ -369,6 +368,11 @@ class GroupChannel(discord.abc.Messageable, Hashable):
self.icon = data.get('icon')
self.name = data.get('name')
+ try:
+ self.recipients = [state.store_user(u) for u in data['recipients']]
+ except KeyError:
+ pass
+
if owner_id == self.me.id:
self.owner = self.me
else:
@@ -438,6 +442,105 @@ class GroupChannel(discord.abc.Messageable, Hashable):
return base
+ @asyncio.coroutine
+ def add_recipients(self, *recipients):
+ """|coro|
+
+ Adds recipients to this group.
+
+ A group can only have a maximum of 10 members.
+ Attempting to add more ends up in an exception. To
+ add a recipient to the group, you must have a relationship
+ with the user of type :attr:`RelationshipType.friend`.
+
+ Parameters
+ -----------
+ \*recipients: :class:`User`
+ An argument list of users to add to this group.
+
+ Raises
+ -------
+ HTTPException
+ Adding a recipient to this group failed.
+ """
+
+ # TODO: wait for the corresponding WS event
+
+ req = self._state.http.add_group_recipient
+ for recipient in recipients:
+ yield from req(self.id, recipient.id)
+
+ @asyncio.coroutine
+ def remove_recipients(self, *recipients):
+ """|coro|
+
+ Removes recipients from this group.
+
+ Parameters
+ -----------
+ \*recipients: :class:`User`
+ An argument list of users to remove from this group.
+
+ Raises
+ -------
+ HTTPException
+ Removing a recipient from this group failed.
+ """
+
+ # TODO: wait for the corresponding WS event
+
+ req = self._state.http.remove_group_recipient
+ for recipient in recipients:
+ yield from req(self.id, recipient.id)
+
+ @asyncio.coroutine
+ def edit(self, **fields):
+ """|coro|
+
+ Edits the group.
+
+ Parameters
+ -----------
+ name: Optional[str]
+ The new name to change the group to.
+ Could be ``None`` to remove the name.
+ icon: Optional[bytes]
+ A bytes-like object representing the new icon.
+ Could be ``None`` to remove the icon.
+
+ Raises
+ -------
+ HTTPException
+ Editing the group failed.
+ """
+
+ try:
+ icon_bytes = fields['icon']
+ except KeyError:
+ pass
+ else:
+ if icon_bytes is not None:
+ fields['icon'] = utils._bytes_to_base64_data(icon_bytes)
+
+ data = yield from self._state.http.edit_group(self.id, **fields)
+ self._update_group(data)
+
+ @asyncio.coroutine
+ def leave(self):
+ """|coro|
+
+ Leave the group.
+
+ If you are the only one in the group, this deletes it as well.
+
+ Raises
+ -------
+ HTTPException
+ Leaving the group failed.
+ """
+
+ yield from self._state.http.leave_group(self.id)
+
def _channel_factory(channel_type):
value = try_enum(ChannelType, channel_type)
if value is ChannelType.text:
diff --git a/discord/http.py b/discord/http.py
index c8b68512..b253449c 100644
--- a/discord/http.py
+++ b/discord/http.py
@@ -249,6 +249,37 @@ class HTTPClient:
def logout(self):
return self.request(Route('POST', '/auth/logout'))
+ # Group functionality
+
+ def start_group(self, user_id, recipients):
+ payload = {
+ 'recipients': recipients
+ }
+
+ return self.request(Route('POST', '/users/{user_id}/channels', user_id=user_id), json=payload)
+
+ def leave_group(self, channel_id):
+ return self.request(Route('DELETE', '/channels/{channel_id}', channel_id=channel_id))
+
+ def add_group_recipient(self, channel_id, user_id):
+ r = Route('PUT', '/channels/{channel_id}/recipients/{user_id}', channel_id=channel_id, user_id=user_id)
+ return self.request(r)
+
+ def remove_group_recipient(self, channel_id, user_id):
+ r = Route('DELETE', '/channels/{channel_id}/recipients/{user_id}', channel_id=channel_id, user_id=user_id)
+ return self.request(r)
+
+ def edit_group(self, channel_id, **options):
+ valid_keys = ('name', 'icon')
+ payload = {
+ k: v for k, v in options.items() if k in valid_keys
+ }
+
+ return self.request(Route('PATCH', '/channels/{channel_id}', channel_id=channel_id), json=payload)
+
+ def convert_group(self, channel_id):
+ return self.request(Route('POST', '/channels/{channel_id}/convert', channel_id=channel_id))
+
# Message management
def start_private_message(self, user_id):
diff --git a/discord/user.py b/discord/user.py
index 47cebde5..cadf84db 100644
--- a/discord/user.py
+++ b/discord/user.py
@@ -308,6 +308,45 @@ class ClientUser(BaseUser):
# manually update data by calling __init__ explicitly.
self.__init__(state=self._state, data=data)
+ @asyncio.coroutine
+ def create_group(self, *recipients):
+ """|coro|
+
+ Creates a group direct message with the recipients
+ provided. These recipients must be have a relationship
+ of type :attr:`RelationshipType.friend`.
+
+ Bot accounts cannot create a group.
+
+ Parameters
+ -----------
+ \*recipients
+ An argument list of :class:`User` to have in
+ your group.
+
+ Return
+ -------
+ :class:`GroupChannel`
+ The new group channel.
+
+ Raises
+ -------
+ HTTPException
+ Failed to create the group direct message.
+ ClientException
+ Attempted to create a group with only one recipient.
+ This does not include yourself.
+ """
+
+ from .channel import GroupChannel
+
+ if len(recipients) < 2:
+ raise ClientException('You must have two or more recipients to create a group.')
+
+ users = [str(u.id) for u in recipients]
+ data = yield from self._state.http.create_group(self.id, users)
+ return GroupChannel(me=self, data=data, state=self._state)
+
class User(BaseUser, discord.abc.Messageable):
"""Represents a Discord user.