Ejemplo n.º 1
0
 async def test_chunked(self) -> None:
     self.assertEqual(
         [chunk async for chunk in mit.chunked(_gen(), 2)], [[0, 1], [2, 3], [4]]
     )
     self.assertEqual(
         [chunk async for chunk in mit.chunked(range(5), 2)], [[0, 1], [2, 3], [4]]
     )
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    async def handle_event(
            self, event: Dict[bytes, bytes]) -> AsyncIterable[Dict[str, Any]]:
        try:
            history_dump = HistoryDumpReceived.deserialize(event)
            await User.get(id=history_dump.user_id)
        except (ValidationError, AttributeError) as e:
            if event and "opening" not in event:
                logger.exception(str(e))
        except DoesNotExist:
            logger.exception("There is no user with id {user_id}",
                             user_id=history_dump.user_id)
        else:
            logger.info(
                "Dump received {dump} n_items:{n_items}",
                dump=history_dump.id,
                n_items=len(history_dump.items),
            )
            history_dump = history_dump.dict()

            async for chunk in chunked(history_dump["items"],
                                       HISTORY_DISTRIBUTOR_CHUNK_LENGTH):
                chunk = {
                    "user_id": history_dump["user_id"],
                    "items": list(chunk)
                }
                data = {"data": orjson.dumps(chunk)}
                yield data

            logger.info(
                "Dump distributed {dump} n_items:{n_items}",
                dump=history_dump["id"],
                n_items=len(history_dump["items"]),
            )
Ejemplo n.º 4
0
    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}")
Ejemplo n.º 5
0
 async def test_chunked_empty(self) -> None:
     self.assertEqual([],
                      [chunk async for chunk in mit.chunked(_empty(), 2)])