From f0fc70b2cf88d64bf38dc737ebf182bb22b90852 Mon Sep 17 00:00:00 2001 From: Rapptz Date: Tue, 14 Jun 2016 20:48:41 -0400 Subject: [PATCH] Add a way to set permission overwrites when creating a channel. --- discord/__init__.py | 2 +- discord/client.py | 71 +++++++++++++++++++++++++++++++++++++++++++-- discord/http.py | 5 +++- 3 files changed, 73 insertions(+), 5 deletions(-) diff --git a/discord/__init__.py b/discord/__init__.py index eeb4b1cad..7bcd47f0b 100644 --- a/discord/__init__.py +++ b/discord/__init__.py @@ -17,7 +17,7 @@ __license__ = 'MIT' __copyright__ = 'Copyright 2015-2016 Rapptz' __version__ = '0.10.0-alpha' -from .client import Client, AppInfo +from .client import Client, AppInfo, ChannelPermissions from .user import User from .game import Game from .channel import Channel, PrivateChannel diff --git a/discord/client.py b/discord/client.py index 9139a3ea2..cec528cdb 100644 --- a/discord/client.py +++ b/discord/client.py @@ -36,7 +36,7 @@ from .object import Object from .role import Role from .errors import * from .state import ConnectionState -from .permissions import Permissions +from .permissions import Permissions, PermissionOverwrite from . import utils, compat from .enums import ChannelType, ServerRegion from .voice_client import VoiceClient @@ -71,6 +71,9 @@ def app_info_icon_url(self): AppInfo.icon_url = property(app_info_icon_url) +ChannelPermissions = namedtuple('ChannelPermissions', 'target overwrite') +ChannelPermissions.__new__.__defaults__ = (PermissionOverwrite(),) + class Client: """Represents a client connection that connects to Discord. This class is used to interact with the Discord WebSocket and API. @@ -1542,13 +1545,47 @@ class Client: yield from self.http.patch(url, json=payload, bucket='move_channel') @asyncio.coroutine - def create_channel(self, server, name, type=None): + def create_channel(self, server, name, *overwrites, type=None): """|coro| Creates a :class:`Channel` in the specified :class:`Server`. Note that you need the proper permissions to create the channel. + The ``overwrites`` argument list can be used to create a 'secret' + channel upon creation. A namedtuple of :class:`ChannelPermissions` + is exposed to create a channel-specific permission overwrite in a more + self-documenting matter. You can also use a regular tuple of ``(target, overwrite)`` + where the ``overwrite`` expected has to be of type :class:`PermissionOverwrite`. + + Examples + ---------- + + Creating a voice channel: + + .. code-block:: python + + await client.create_channel(server, 'Voice', type=discord.ChannelType.voice) + + Creating a 'secret' text channel: + + .. code-block:: python + + everyone_perms = discord.PermissionOverwrite(read_messages=False) + my_perms = discord.PermissionOverwrite(read_messages=True) + + everyone = discord.ChannelPermissions(target=server.default_role, overwrite=everyone_perms) + mine = discord.ChannelPermissions(target=server.me, overwrite=my_perms) + await client.create_channel(server, 'secret', everyone, mine) + + Or in a more 'compact' way: + + .. code-block:: python + + everyone = discord.PermissionOverwrite(read_messages=False) + mine = discord.PermissionOverwrite(read_messages=True) + await client.create_channel(server, 'secret', (server.default_role, everyone), (server.me, mine)) + Parameters ----------- server : :class:`Server` @@ -1557,6 +1594,9 @@ class Client: The channel's name. type : :class:`ChannelType` The type of channel to create. Defaults to :attr:`ChannelType.text`. + overwrites: + An argument list of channel specific overwrites to apply on the channel on + creation. Useful for creating 'secret' channels. Raises ------- @@ -1566,6 +1606,8 @@ class Client: The server specified was not found. HTTPException Creating the channel failed. + InvalidArgument + The permission overwrite array is not in proper form. Returns ------- @@ -1577,7 +1619,30 @@ class Client: if type is None: type = ChannelType.text - data = yield from self.http.create_channel(server.id, name, str(type)) + perms = [] + for overwrite in overwrites: + target = overwrite[0] + perm = overwrite[1] + if not isinstance(perm, PermissionOverwrite): + raise InvalidArgument('Expected PermissionOverwrite received {0.__name__}'.format(type(perm))) + + allow, deny = perm.pair() + payload = { + 'allow': allow.value, + 'deny': deny.value, + 'id': target.id + } + + if isinstance(target, User): + payload['type'] = 'member' + elif isinstance(target, Role): + payload['type'] = 'role' + else: + raise InvalidArgument('Expected Role, User, or Member target, received {0.__name__}'.format(type(target))) + + perms.append(payload) + + data = yield from self.http.create_channel(server.id, name, str(type), permission_overwrites=perms) channel = Channel(server=server, **data) return channel diff --git a/discord/http.py b/discord/http.py index aa5ef47ae..9cd46bad9 100644 --- a/discord/http.py +++ b/discord/http.py @@ -344,13 +344,16 @@ class HTTPClient: return self.patch(url, json=payload, bucket=_func_()) - def create_channel(self, guild_id, name, channe_type): + def create_channel(self, guild_id, name, channe_type, permission_overwrites=None): url = '{0.GUILDS}/{1}/channels'.format(self, guild_id) payload = { 'name': name, 'type': channe_type } + if permission_overwrites is not None: + payload['permission_overwrites'] = permission_overwrites + return self.post(url, json=payload, bucket=_func_()) def delete_channel(self, channel_id):