Move purge and delete_messages from Messageable.
This is a breaking change. Move these two to TextChannel since the other things that implement Messageable cannot reliably do bulk delete actions in their respective channels.
This commit is contained in:
		@@ -30,14 +30,21 @@ from .role import Role
 | 
			
		||||
from .user import User
 | 
			
		||||
from .member import Member
 | 
			
		||||
from . import utils
 | 
			
		||||
from .errors import ClientException, NoMoreItems
 | 
			
		||||
 | 
			
		||||
import discord.abc
 | 
			
		||||
 | 
			
		||||
import copy
 | 
			
		||||
import time
 | 
			
		||||
import asyncio
 | 
			
		||||
 | 
			
		||||
__all__ = ('TextChannel', 'VoiceChannel', 'DMChannel', 'GroupChannel', '_channel_factory')
 | 
			
		||||
 | 
			
		||||
@asyncio.coroutine
 | 
			
		||||
def _single_delete_strategy(messages):
 | 
			
		||||
    for m in messages:
 | 
			
		||||
        yield from m.delete()
 | 
			
		||||
 | 
			
		||||
class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
 | 
			
		||||
    """Represents a Discord guild text channel.
 | 
			
		||||
 | 
			
		||||
@@ -141,6 +148,143 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
 | 
			
		||||
            data = yield from self._state.http.edit_channel(self.id, **options)
 | 
			
		||||
            self._update(self.guild, data)
 | 
			
		||||
 | 
			
		||||
    @asyncio.coroutine
 | 
			
		||||
    def delete_messages(self, messages):
 | 
			
		||||
        """|coro|
 | 
			
		||||
 | 
			
		||||
        Deletes a list of messages. This is similar to :meth:`Message.delete`
 | 
			
		||||
        except it bulk deletes multiple messages.
 | 
			
		||||
 | 
			
		||||
        Usable only by bot accounts.
 | 
			
		||||
 | 
			
		||||
        Parameters
 | 
			
		||||
        -----------
 | 
			
		||||
        messages : iterable of :class:`Message`
 | 
			
		||||
            An iterable of messages denoting which ones to bulk delete.
 | 
			
		||||
 | 
			
		||||
        Raises
 | 
			
		||||
        ------
 | 
			
		||||
        ClientException
 | 
			
		||||
            The number of messages to delete is less than 2 or more than 100.
 | 
			
		||||
        Forbidden
 | 
			
		||||
            You do not have proper permissions to delete the messages or
 | 
			
		||||
            you're not using a bot account.
 | 
			
		||||
        HTTPException
 | 
			
		||||
            Deleting the messages failed.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        messages = list(messages)
 | 
			
		||||
        if len(messages) > 100 or len(messages) < 2:
 | 
			
		||||
            raise ClientException('Can only delete messages in the range of [2, 100]')
 | 
			
		||||
 | 
			
		||||
        message_ids = [m.id for m in messages]
 | 
			
		||||
        channel = yield from self._get_channel()
 | 
			
		||||
 | 
			
		||||
        yield from self._state.http.delete_messages(channel.id, message_ids)
 | 
			
		||||
 | 
			
		||||
    @asyncio.coroutine
 | 
			
		||||
    def purge(self, *, limit=100, check=None, before=None, after=None, around=None):
 | 
			
		||||
        """|coro|
 | 
			
		||||
 | 
			
		||||
        Purges a list of messages that meet the criteria given by the predicate
 | 
			
		||||
        ``check``. If a ``check`` is not provided then all messages are deleted
 | 
			
		||||
        without discrimination.
 | 
			
		||||
 | 
			
		||||
        You must have :attr:`Permissions.manage_messages` permission to delete
 | 
			
		||||
        messages even if they are your own (unless you are a user account).
 | 
			
		||||
        The :attr:`Permissions.read_message_history` permission is also needed
 | 
			
		||||
        to retrieve message history.
 | 
			
		||||
 | 
			
		||||
        Internally, this employs a different number of strategies depending
 | 
			
		||||
        on the conditions met such as if a bulk delete is possible or if
 | 
			
		||||
        the account is a user bot or not.
 | 
			
		||||
 | 
			
		||||
        Parameters
 | 
			
		||||
        -----------
 | 
			
		||||
        limit: int
 | 
			
		||||
            The number of messages to search through. This is not the number
 | 
			
		||||
            of messages that will be deleted, though it can be.
 | 
			
		||||
        check: predicate
 | 
			
		||||
            The function used to check if a message should be deleted.
 | 
			
		||||
            It must take a :class:`Message` as its sole parameter.
 | 
			
		||||
        before
 | 
			
		||||
            Same as ``before`` in :meth:`history`.
 | 
			
		||||
        after
 | 
			
		||||
            Same as ``after`` in :meth:`history`.
 | 
			
		||||
        around
 | 
			
		||||
            Same as ``around`` in :meth:`history`.
 | 
			
		||||
 | 
			
		||||
        Raises
 | 
			
		||||
        -------
 | 
			
		||||
        Forbidden
 | 
			
		||||
            You do not have proper permissions to do the actions required.
 | 
			
		||||
        HTTPException
 | 
			
		||||
            Purging the messages failed.
 | 
			
		||||
 | 
			
		||||
        Examples
 | 
			
		||||
        ---------
 | 
			
		||||
 | 
			
		||||
        Deleting bot's messages ::
 | 
			
		||||
 | 
			
		||||
            def is_me(m):
 | 
			
		||||
                return m.author == client.user
 | 
			
		||||
 | 
			
		||||
            deleted = await channel.purge(limit=100, check=is_me)
 | 
			
		||||
            await channel.send_message('Deleted {} message(s)'.format(len(deleted)))
 | 
			
		||||
 | 
			
		||||
        Returns
 | 
			
		||||
        --------
 | 
			
		||||
        list
 | 
			
		||||
            The list of messages that were deleted.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        if check is None:
 | 
			
		||||
            check = lambda m: True
 | 
			
		||||
 | 
			
		||||
        iterator = self.history(limit=limit, before=before, after=after, around=around)
 | 
			
		||||
        ret = []
 | 
			
		||||
        count = 0
 | 
			
		||||
 | 
			
		||||
        minimum_time = int((time.time() - 14 * 24 * 60 * 60) * 1000.0 - 1420070400000) << 22
 | 
			
		||||
        strategy = self.delete_messages if self._state.is_bot else _single_delete_strategy
 | 
			
		||||
 | 
			
		||||
        while True:
 | 
			
		||||
            try:
 | 
			
		||||
                msg = yield from iterator.get()
 | 
			
		||||
            except NoMoreItems:
 | 
			
		||||
                # no more messages to poll
 | 
			
		||||
                if count >= 2:
 | 
			
		||||
                    # more than 2 messages -> bulk delete
 | 
			
		||||
                    to_delete = ret[-count:]
 | 
			
		||||
                    yield from strategy(to_delete)
 | 
			
		||||
                elif count == 1:
 | 
			
		||||
                    # delete a single message
 | 
			
		||||
                    yield from ret[-1].delete()
 | 
			
		||||
 | 
			
		||||
                return ret
 | 
			
		||||
            else:
 | 
			
		||||
                if count == 100:
 | 
			
		||||
                    # we've reached a full 'queue'
 | 
			
		||||
                    to_delete = ret[-100:]
 | 
			
		||||
                    yield from strategy(to_delete)
 | 
			
		||||
                    count = 0
 | 
			
		||||
                    yield from asyncio.sleep(1)
 | 
			
		||||
 | 
			
		||||
                if check(msg):
 | 
			
		||||
                    if msg.id < minimum_time:
 | 
			
		||||
                        # older than 14 days old
 | 
			
		||||
                        if count == 1:
 | 
			
		||||
                            yield from ret[-1].delete()
 | 
			
		||||
                        elif count >= 2:
 | 
			
		||||
                            to_delete = ret[-count:]
 | 
			
		||||
                            yield from strategy(to_delete)
 | 
			
		||||
 | 
			
		||||
                        count = 0
 | 
			
		||||
                        strategy = _single_delete_strategy
 | 
			
		||||
 | 
			
		||||
                    count += 1
 | 
			
		||||
                    ret.append(msg)
 | 
			
		||||
 | 
			
		||||
class VoiceChannel(discord.abc.GuildChannel, Hashable):
 | 
			
		||||
    """Represents a Discord guild voice channel.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user