aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRapptz <[email protected]>2016-05-10 08:38:12 -0400
committerRapptz <[email protected]>2016-05-10 08:43:09 -0400
commit1f86a9b795326ce72a03f4bde6dbebb676ff60d8 (patch)
tree7204baa041f3332f9181025e79e21607b1627c37
parentAdd Client.delete_messages for bulk delete. (diff)
downloaddiscord.py-1f86a9b795326ce72a03f4bde6dbebb676ff60d8.tar.xz
discord.py-1f86a9b795326ce72a03f4bde6dbebb676ff60d8.zip
Add Client.purge_from as a high level interface around bulk delete.
-rw-r--r--discord/client.py77
-rw-r--r--discord/iterators.py12
2 files changed, 84 insertions, 5 deletions
diff --git a/discord/client.py b/discord/client.py
index b90bb813..7c8915f1 100644
--- a/discord/client.py
+++ b/discord/client.py
@@ -1020,6 +1020,81 @@ class Client:
yield from response.release()
@asyncio.coroutine
+ def purge_from(self, channel, *, limit=100, check=None, before=None, after=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 Manage Messages permission to delete messages that aren't
+ your own. The Read Message History permission is also needed to retrieve
+ message history.
+
+ Parameters
+ -----------
+ channel : :class:`Channel`
+ The channel to purge from.
+ 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 function should be deleted.
+ It must take a :class:`Message` as its sole parameter.
+ before : :class:`Message`
+ The message before scanning for purging must be.
+ after : :class:`Message`
+ The message after scanning for purging must be.
+
+ Raises
+ -------
+ Forbidden
+ You do not have proper permissions to do the actions required.
+ HTTPException
+ Purging the messages failed.
+
+ Returns
+ --------
+ list
+ The list of messages that were deleted.
+ """
+
+ if check is None:
+ check = lambda m: True
+
+ iterator = LogsFromIterator(self, channel, limit, before, after)
+ ret = []
+ count = 0
+
+ while True:
+ try:
+ msg = yield from iterator.iterate()
+ except asyncio.QueueEmpty:
+ # no more messages to poll
+ if count >= 2:
+ # more than 2 messages -> bulk delete
+ to_delete = ret[-count:]
+ yield from self.delete_messages(to_delete)
+ yield from asyncio.sleep(1)
+ elif count == 1:
+ # delete a single message
+ yield from self.delete_message(ret[-1])
+
+ return ret
+ else:
+ if count == 100:
+ # we've reached a full 'queue'
+ to_delete = ret[-100:]
+ yield from self.delete_messages(to_delete)
+ count = 0
+ yield from asyncio.sleep(1)
+ else:
+ # queue isn't full so just add it in there
+ if check(msg):
+ count += 1
+ ret.append(msg)
+
+ @asyncio.coroutine
def edit_message(self, message, new_content):
"""|coro|
@@ -1462,7 +1537,7 @@ class Client:
Forbidden
You do not have permissions to change the nickname.
HTTPException
- Editing the channel failed.
+ Changing the nickname failed.
"""
if member == self.user:
diff --git a/discord/iterators.py b/discord/iterators.py
index 6a1d8952..f74227d8 100644
--- a/discord/iterators.py
+++ b/discord/iterators.py
@@ -52,6 +52,13 @@ class LogsFromIterator:
for element in data:
yield from self.messages.put(Message(channel=self.channel, **element))
+ @asyncio.coroutine
+ def iterate(self):
+ if self.messages.empty():
+ yield from self.fill_messages()
+
+ return self.messages.get_nowait()
+
if PY35:
@asyncio.coroutine
def __aiter__(self):
@@ -59,11 +66,8 @@ class LogsFromIterator:
@asyncio.coroutine
def __anext__(self):
- if self.messages.empty():
- yield from self.fill_messages()
-
try:
- msg = self.messages.get_nowait()
+ msg = yield from self.iterate()
return msg
except asyncio.QueueEmpty:
# if we're still empty at this point...