async def purge(self, ctx, num: int, *targets: User): """Bulk delete messages of a certain amount posted by some targeted Discord users, if not providedit just deletes all the messages which it encounters""" total_deleted = 0 messages = ctx.history(limit=None) await messages.__anext__() # includes the invoker's message, so skip that. # discord has a bulk-deletion method which has limits that, # messages cannot be deleted older than 14 days. # cannot delete more than 100 messages at once. async for chunk in chunked(map(lambda m: m[1], takewhile( lambda m: m[0] < num and (ctx.message.created_at - m[1].created_at).days < 14, filterfalse(lambda m: not(m[1].author in targets or not targets), aenumerate(messages)))), 100): chunk = list(chunk) await ctx.channel.delete_messages(chunk) # delete 100 messages at once. total_deleted += len(chunk) # for the rest follow the manual deletion way. async for msg in messages: if not total_deleted <= num: await ctx.send(f"Purged {num} messages in {ctx.channel.mention}.", delete_after=8) break if msg.author in targets or targets is None: await msg.delete() total_deleted += 1
async def test_takewhile_coroutine_list(self): async def pred(x): return x < 3 it = ait.takewhile(pred, srange) for k in [1, 2]: self.assertEqual(await ait.next(it), k) with self.assertRaises(StopAsyncIteration): await ait.next(it)
async def test_takewhile_coroutine_gen(self): def gen(): yield 1 yield 2 yield 3 async def pred(x): return x < 3 it = ait.takewhile(pred, gen()) for k in [1, 2]: self.assertEqual(await ait.next(it), k) with self.assertRaises(StopAsyncIteration): await ait.next(it)
async def purge(self, ctx, end: MessageConverter, begin: MessageConverter = None): """Delete a range of messages defined by two sentinel messages (inclusive)""" total = 0 # deleted total ref_time = ctx.message.created_at messages = ctx.history(after=end, before=begin, oldest_first=False) if not begin: messages.__anext__() # skip invoking message # message matching is defined mathematically as, # Selection = [Begin..End] ⊆ Messages # # for bulk-deletion specifically, # BulkDelete = {m ∈ Selection | Age(m) ≤ 14} [(2 ≤ |Selection| ≤ 100)] bulk_msgs = takewhile(lambda m: (ref_time - m.created_at).days < 15, messages) async for bulk in chunked(bulk_msgs, 100): if len(bulk) == 1: messages = chain(bulk, messages) break # queue remaining for manual deletion. await ctx.channel.delete_messages(bulk) # 100 snowflakes/request total += len(bulk) # if can't bulk delete anymore, do manual. async for m in messages: await m.delete() total += 1 await end.delete() await ctx.send(f"Purged {total+1} messages in {ctx.channel.mention}")
async def test_takewhile_empty(self): def pred(x): return x < 3 values = await ait.list(ait.takewhile(pred, [])) self.assertEqual(values, [])