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
def filter_history(channel: discord.TextChannel, **kwargs) -> typing.Coroutine[typing.Any, None, list[discord.Message]]: check = kwargs.pop('check', lambda m: True) limit = kwargs.pop('limit', sys.maxsize) return aioitertools.list(aioitertools.map( operator.itemgetter(1), aioitertools.zip(range(limit), channel.history(limit=None, **kwargs).filter(check)) ))
async def test_map_coroutine_list(self): async def double(x): await asyncio.sleep(0.0001) return x * 2 idx = 0 async for value in ait.map(double, slist): self.assertEqual(value, slist[idx] * 2) idx += 1
async def test_map_function_async_generator(self): async def gen(): for item in slist: yield item idx = 0 async for value in ait.map(str.lower, gen()): self.assertEqual(value, slist[idx].lower()) idx += 1
async def test_map_coroutine_generator(self): async def gen(): for item in slist: yield item async def double(x): await asyncio.sleep(0.0001) return x * 2 idx = 0 async for value in ait.map(double, gen()): self.assertEqual(value, slist[idx] * 2) idx += 1
async def _insert_parent_func(self, func): """ Given a recursive dict in self.iter backed by generator expressions, insert `func' right above the leaves. self.parent_iter and self.parent_key are used to quickly locate the parents of leaf nodes. """ if not self.parent_iter or not self.parent_key: self.iter = aioitertools.map( partial(apply_func, map_func=self.map_func), self.iter) self.root = self.iter return # we need to be able to iterate over self.parent_iter multiple # times self.parent_iter, tmp_it = await aitertools.tee(self.parent_iter) async for p in tmp_it: pkey = str(self.parent_key) if isinstance(p[pkey], FuncStack): p[pkey].append(self.map_func) else: p[pkey] = FuncStack([p[pkey], self.map_func])
async def test_map_function_list(self): idx = 0 async for value in ait.map(str.lower, slist): self.assertEqual(value, slist[idx].lower()) idx += 1