aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--discord/abc.py8
-rw-r--r--discord/channel.py133
-rw-r--r--discord/enums.py1
-rw-r--r--discord/guild.py12
-rw-r--r--docs/api.rst4
5 files changed, 150 insertions, 8 deletions
diff --git a/discord/abc.py b/discord/abc.py
index 2280bd60..8345786c 100644
--- a/discord/abc.py
+++ b/discord/abc.py
@@ -187,13 +187,17 @@ class GuildChannel:
def __str__(self):
return self.name
+ @property
+ def _sorting_bucket(self):
+ raise NotImplementedError
+
async def _move(self, position, parent_id=None, lock_permissions=False, *, reason):
if position < 0:
raise InvalidArgument('Channel position cannot be less than 0.')
http = self._state.http
- cls = type(self)
- channels = [c for c in self.guild.channels if isinstance(c, cls)]
+ bucket = self._sorting_bucket
+ channels = [c for c in self.guild.channels if c._sorting_bucket == bucket]
if position >= len(channels):
raise InvalidArgument('Channel position cannot be greater than {}'.format(len(channels) - 1))
diff --git a/discord/channel.py b/discord/channel.py
index 44b7f2eb..42b13326 100644
--- a/discord/channel.py
+++ b/discord/channel.py
@@ -35,7 +35,15 @@ from . import utils
from .errors import ClientException, NoMoreItems
from .webhook import Webhook
-__all__ = ['TextChannel', 'VoiceChannel', 'DMChannel', 'CategoryChannel', 'GroupChannel', '_channel_factory']
+__all__ = [
+ 'TextChannel',
+ 'VoiceChannel',
+ 'DMChannel',
+ 'CategoryChannel',
+ 'StoreChannel',
+ 'GroupChannel',
+ '_channel_factory',
+]
async def _single_delete_strategy(messages):
for m in messages:
@@ -112,6 +120,10 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
async def _get_channel(self):
return self
+ @property
+ def _sorting_bucket(self):
+ return ChannelType.text.value
+
def permissions_for(self, member):
base = super().permissions_for(member)
@@ -458,6 +470,10 @@ class VoiceChannel(discord.abc.Connectable, discord.abc.GuildChannel, Hashable):
self._fill_overwrites(data)
@property
+ def _sorting_bucket(self):
+ return ChannelType.voice.value
+
+ @property
def members(self):
"""Returns a list of :class:`Member` that are currently inside this voice channel."""
ret = []
@@ -572,6 +588,10 @@ class CategoryChannel(discord.abc.GuildChannel, Hashable):
self.position = data['position']
self._fill_overwrites(data)
+ @property
+ def _sorting_bucker(self):
+ return ChannelType.category
+
def is_nsfw(self):
"""Checks if the category is NSFW."""
n = self.name
@@ -663,6 +683,115 @@ class CategoryChannel(discord.abc.GuildChannel, Hashable):
"""
return await self.guild.create_voice_channel(name, overwrites=overwrites, category=self, reason=reason, **options)
+class StoreChannel(discord.abc.GuildChannel, Hashable):
+ """Represents a Discord guild store channel.
+
+ .. container:: operations
+
+ .. describe:: x == y
+
+ Checks if two channels are equal.
+
+ .. describe:: x != y
+
+ Checks if two channels are not equal.
+
+ .. describe:: hash(x)
+
+ Returns the channel's hash.
+
+ .. describe:: str(x)
+
+ Returns the channel's name.
+
+ Attributes
+ -----------
+ name: :class:`str`
+ The channel name.
+ guild: :class:`Guild`
+ The guild the channel belongs to.
+ id: :class:`int`
+ The channel ID.
+ category_id: :class:`int`
+ The category channel ID this channel belongs to.
+ position: :class:`int`
+ The position in the channel list. This is a number that starts at 0. e.g. the
+ top channel is position 0.
+ """
+ __slots__ = ('name', 'id', 'guild', '_state', 'nsfw',
+ 'category_id', 'position', '_overwrites',)
+
+ def __init__(self, *, state, guild, data):
+ self._state = state
+ self.id = int(data['id'])
+ self._update(guild, data)
+
+ def __repr__(self):
+ return '<StoreChannel id={0.id} name={0.name!r} position={0.position}>'.format(self)
+
+ def _update(self, guild, data):
+ self.guild = guild
+ self.name = data['name']
+ self.category_id = utils._get_as_snowflake(data, 'parent_id')
+ self.position = data['position']
+ self.nsfw = data.get('nsfw', False)
+ self._fill_overwrites(data)
+
+ @property
+ def _sorting_bucket(self):
+ return ChannelType.text.value
+
+ def permissions_for(self, member):
+ base = super().permissions_for(member)
+
+ # store channels do not have voice related permissions
+ denied = Permissions.voice()
+ base.value &= ~denied.value
+ return base
+
+ permissions_for.__doc__ = discord.abc.GuildChannel.permissions_for.__doc__
+
+ def is_nsfw(self):
+ """Checks if the channel is NSFW."""
+ n = self.name
+ return self.nsfw or n == 'nsfw' or n[:5] == 'nsfw-'
+
+ async def edit(self, *, reason=None, **options):
+ """|coro|
+
+ Edits the channel.
+
+ You must have the :attr:`~Permissions.manage_channels` permission to
+ use this.
+
+ Parameters
+ ----------
+ name: :class:`str`
+ The new channel name.
+ position: :class:`int`
+ The new channel's position.
+ nsfw: :class:`bool`
+ To mark the channel as NSFW or not.
+ sync_permissions: :class:`bool`
+ Whether to sync permissions with the channel's new or pre-existing
+ category. Defaults to ``False``.
+ category: Optional[:class:`CategoryChannel`]
+ The new category for this channel. Can be ``None`` to remove the
+ category.
+ reason: Optional[:class:`str`]
+ The reason for editing this channel. Shows up on the audit log.
+
+ Raises
+ ------
+ InvalidArgument
+ If position is less than 0 or greater than the number of channels.
+ Forbidden
+ You do not have permissions to edit the channel.
+ HTTPException
+ Editing the channel failed.
+ """
+ await self._edit(options, reason=reason)
+
class DMChannel(discord.abc.Messageable, Hashable):
"""Represents a Discord direct message channel.
@@ -977,5 +1106,7 @@ def _channel_factory(channel_type):
return GroupChannel, value
elif value is ChannelType.news:
return TextChannel, value
+ elif value is ChannelType.store:
+ return StoreChannel, value
else:
return None, value
diff --git a/discord/enums.py b/discord/enums.py
index cfe475c6..ab049e2d 100644
--- a/discord/enums.py
+++ b/discord/enums.py
@@ -39,6 +39,7 @@ class ChannelType(Enum):
group = 3
category = 4
news = 5
+ store = 6
def __str__(self):
return self.name
diff --git a/discord/guild.py b/discord/guild.py
index 52199e52..5ccf293c 100644
--- a/discord/guild.py
+++ b/discord/guild.py
@@ -261,13 +261,15 @@ class Guild(Hashable):
if 'channels' in data:
channels = data['channels']
for c in channels:
- if c['type'] == ChannelType.text.value or c['type'] == ChannelType.news.value:
+ c_type = c['type']
+ if c_type in (ChannelType.text.value, ChannelType.news.value):
self._add_channel(TextChannel(guild=self, data=c, state=self._state))
- elif c['type'] == ChannelType.voice.value:
+ elif c_type == ChannelType.voice.value:
self._add_channel(VoiceChannel(guild=self, data=c, state=self._state))
- elif c['type'] == ChannelType.category.value:
+ elif c_type == ChannelType.category.value:
self._add_channel(CategoryChannel(guild=self, data=c, state=self._state))
-
+ elif c_type == ChannelType.store.value:
+ self._add_channel(StoreChannel(guild=self, data=c, state=self._state))
@property
def channels(self):
@@ -359,7 +361,7 @@ class Guild(Hashable):
as_list = [(_get(k), v) for k, v in grouped.items()]
as_list.sort(key=key)
for _, channels in as_list:
- channels.sort(key=lambda c: (not isinstance(c, TextChannel), c.position, c.id))
+ channels.sort(key=lambda c: (c._sorting_bucket, c.position, c.id))
return as_list
def get_channel(self, channel_id):
diff --git a/docs/api.rst b/docs/api.rst
index d1d2e754..de55e6f5 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -679,6 +679,10 @@ All enumerations are subclasses of `enum`_.
A guild news channel.
+ .. attribute:: store
+
+ A guild store channel.
+
.. class:: MessageType
Specifies the type of :class:`Message`. This is used to denote if a message