From d5b616fa1168dddaffd2a16d6d87c2e6406a4fc1 Mon Sep 17 00:00:00 2001 From: Rapptz Date: Sat, 31 Dec 2016 06:58:05 -0500 Subject: [PATCH] Rename MessageChannel abc to Messageable. --- discord/abc.py | 57 ++++++++++++++++++++------------- discord/channel.py | 27 ++++++++++------ discord/ext/commands/context.py | 19 +++++------ discord/reaction.py | 2 +- 4 files changed, 62 insertions(+), 43 deletions(-) diff --git a/discord/abc.py b/discord/abc.py index d50966e49..05f4eb701 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -466,18 +466,22 @@ class GuildChannel: raise InvalidArgument('Invalid overwrite type provided.') -class MessageChannel(metaclass=abc.ABCMeta): +class Messageable(metaclass=abc.ABCMeta): __slots__ = () @abc.abstractmethod - def _get_destination(self): + def _get_channel(self): + raise NotImplementedError + + @abc.abstractmethod + def _get_guild_id(self): raise NotImplementedError @asyncio.coroutine def send(self, content=None, *, tts=False, embed=None, file=None, filename=None, delete_after=None): """|coro| - Sends a message to the channel with the content given. + Sends a message to the destination with the content given. The content must be a type that can convert to a string through ``str(content)``. If the content is set to ``None`` (the default), then the ``embed`` parameter must @@ -532,7 +536,8 @@ class MessageChannel(metaclass=abc.ABCMeta): The message that was sent. """ - channel_id, guild_id = self._get_destination() + channel = self._get_channel() + guild_id = self._get_guild_id() state = self._state content = str(content) if content else None if embed is not None: @@ -547,12 +552,12 @@ class MessageChannel(metaclass=abc.ABCMeta): except TypeError: buffer = file - data = yield from state.http.send_file(channel_id, buffer, guild_id=guild_id, filename=filename, + data = yield from state.http.send_file(channel.id, buffer, guild_id=guild_id, filename=filename, content=content, tts=tts, embed=embed) else: - data = yield from state.http.send_message(channel_id, content, guild_id=guild_id, tts=tts, embed=embed) + data = yield from state.http.send_message(channel.id, content, guild_id=guild_id, tts=tts, embed=embed) - ret = Message(channel=self, state=state, data=data) + ret = Message(channel=channel, state=state, data=data) if delete_after is not None: @asyncio.coroutine def delete(): @@ -565,22 +570,27 @@ class MessageChannel(metaclass=abc.ABCMeta): return ret @asyncio.coroutine - def send_typing(self): + def trigger_typing(self): """|coro| - Send a *typing* status to the channel. + Triggers a *typing* indicator to the destination. - *Typing* status will go away after 10 seconds, or after a message is sent. + *Typing* indicator will go away after 10 seconds, or after a message is sent. """ - channel_id, _ = self._get_destination() - yield from self._state.http.send_typing(channel_id) + channel = self._get_channel() + yield from self._state.http.send_typing(channel.id) def typing(self): """Returns a context manager that allows you to type for an indefinite period of time. This is useful for denoting long computations in your bot. + .. note:: + + This is both a regular context manager and an async context manager. + This means that both ``with`` and ``async with`` work with this. + Example Usage: :: with channel.typing(): @@ -588,13 +598,13 @@ class MessageChannel(metaclass=abc.ABCMeta): await channel.send_message('done!') """ - return Typing(self) + return Typing(self._get_channel()) @asyncio.coroutine def get_message(self, id): """|coro| - Retrieves a single :class:`Message` from a channel. + Retrieves a single :class:`Message` from the destination. This can only be used by bot accounts. @@ -618,8 +628,9 @@ class MessageChannel(metaclass=abc.ABCMeta): Retrieving the message failed. """ - data = yield from self._state.http.get_message(self.id, id) - return Message(channel=self, state=self._state, data=data) + channel = self._get_channel() + data = yield from self._state.http.get_message(channel.id, id) + return Message(channel=channel, state=self._state, data=data) @asyncio.coroutine def delete_messages(self, messages): @@ -651,9 +662,10 @@ class MessageChannel(metaclass=abc.ABCMeta): raise ClientException('Can only delete messages in the range of [2, 100]') message_ids = [m.id for m in messages] - channel_id, guild_id = self._get_destination() + channel = self._get_channel() + guild_id = self._get_guild_id() - yield from self._state.http.delete_messages(channel_id, message_ids, guild_id) + yield from self._state.http.delete_messages(channel.id, message_ids, guild_id) @asyncio.coroutine def pins(self): @@ -667,12 +679,13 @@ class MessageChannel(metaclass=abc.ABCMeta): Retrieving the pinned messages failed. """ + channel = self._get_channel() state = self._state - data = yield from state.http.pins_from(self.id) - return [Message(channel=self, state=state, data=m) for m in data] + data = yield from state.http.pins_from(channel.id) + return [Message(channel=channel, state=state, data=m) for m in data] def history(self, *, limit=100, before=None, after=None, around=None, reverse=None): - """Return an async iterator that enables receiving the channel's message history. + """Return an async iterator that enables receiving the destination's message history. You must have Read Message History permissions to use this. @@ -734,7 +747,7 @@ class MessageChannel(metaclass=abc.ABCMeta): if message.author == client.user: counter += 1 """ - return LogsFromIterator(self, limit=limit, before=before, after=after, around=around, reverse=reverse) + return LogsFromIterator(self._get_channel(), limit=limit, before=before, after=after, around=around, reverse=reverse) @asyncio.coroutine def purge(self, *, limit=100, check=None, before=None, after=None, around=None): diff --git a/discord/channel.py b/discord/channel.py index 80ecdaabd..5be646cb7 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -38,7 +38,7 @@ import asyncio __all__ = ('TextChannel', 'VoiceChannel', 'DMChannel', 'GroupChannel', '_channel_factory') -class TextChannel(discord.abc.MessageChannel, discord.abc.GuildChannel, Hashable): +class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable): """Represents a Discord guild text channel. Supported Operations: @@ -88,8 +88,11 @@ class TextChannel(discord.abc.MessageChannel, discord.abc.GuildChannel, Hashable self.position = data['position'] self._fill_overwrites(data) - def _get_destination(self): - return self.id, self.guild.id + def _get_channel(self): + return self + + def _get_guild_id(self): + return self.guild.id @asyncio.coroutine def edit(self, **options): @@ -224,7 +227,7 @@ class VoiceChannel(discord.abc.GuildChannel, Hashable): data = yield from self._state.http.edit_channel(self.id, **options) self._update(self.guild, data) -class DMChannel(discord.abc.MessageChannel, Hashable): +class DMChannel(discord.abc.Messageable, Hashable): """Represents a Discord direct message channel. Supported Operations: @@ -259,8 +262,11 @@ class DMChannel(discord.abc.MessageChannel, Hashable): self.me = me self.id = int(data['id']) - def _get_destination(self): - return self.id, None + def _get_channel(self): + return self + + def _get_guild_id(self): + return None def __str__(self): return 'Direct Message with %s' % self.recipient @@ -302,7 +308,7 @@ class DMChannel(discord.abc.MessageChannel, Hashable): base.manage_messages = False return base -class GroupChannel(discord.abc.MessageChannel, Hashable): +class GroupChannel(discord.abc.Messageable, Hashable): """Represents a Discord group channel. Supported Operations: @@ -354,8 +360,11 @@ class GroupChannel(discord.abc.MessageChannel, Hashable): else: self.owner = discord.utils.find(lambda u: u.id == owner_id, self.recipients) - def _get_destination(self): - return self.id, None + def _get_channel(self): + return self + + def _get_guild_id(self): + return None def __str__(self): if self.name: diff --git a/discord/ext/commands/context.py b/discord/ext/commands/context.py index efaa5b43d..ff78c562a 100644 --- a/discord/ext/commands/context.py +++ b/discord/ext/commands/context.py @@ -27,14 +27,14 @@ import asyncio import discord.abc import discord.utils -class Context(discord.abc.MessageChannel): +class Context(discord.abc.Messageable): """Represents the context in which a command is being invoked under. This class contains a lot of meta data to help you understand more about the invocation context. This class is not created manually and is instead passed around to commands by passing in :attr:`Command.pass_context`. - This class implements the :class:`abc.MessageChannel` ABC. + This class implements the :class:`abc.Messageable` ABC. Attributes ----------- @@ -117,8 +117,12 @@ class Context(discord.abc.MessageChannel): ret = yield from command.callback(*arguments, **kwargs) return ret - def _get_destination(self): - return self.channel.id, getattr(self.guild, 'id', None) + def _get_channel(self): + return self.channel + + def _get_guild_id(self): + g = self.guild + return g.id if g is not None else None @property def cog(self): @@ -128,13 +132,6 @@ class Context(discord.abc.MessageChannel): return None return self.command.instance - @discord.utils.cached_property - def id(self): - # we need this to meet MessageChannel abc - # it is purposefully undocumented because it makes no logistic sense - # outside of providing the sugar of the main class. - return self.channel.id - @discord.utils.cached_property def guild(self): """Returns the guild associated with this context's command. None if not available.""" diff --git a/discord/reaction.py b/discord/reaction.py index d80f716b0..9c75bfec0 100644 --- a/discord/reaction.py +++ b/discord/reaction.py @@ -113,7 +113,7 @@ class Reaction: A list of users who reacted to the message. """ - # TODO: Return an iterator a la `MessageChannel.history`? + # TODO: Return an iterator a la `Messageable.history`? if self.custom_emoji: emoji = '{0.name}:{0.id}'.format(self.emoji)