Пример #1
0
    async def inv(
        self,
        ctx,
        channel: Optional[Union[discord.TextChannel,
                                discord.VoiceChannel]] = None,
        days: Optional[NonNegative[float]] = None,
        uses: Optional[NonNegative[int]] = None,
        amount: Optional[NonNegative[int]] = None,
        *,
        reason: str = None,
    ):
        """
        Create one or several invites with the specified parameters.

        For specifying unlimited days or uses, use 0.

        Defaults can be set with `[p]inv set`.
        If no defaults are found, channel defaults to the current channel,
        days defaults to 1, and uses defaults to 0 (infinite).

        Uses will always be finite if days is infinite.
        """
        settings = await self.config.guild(ctx.guild).all()
        if not channel:
            channel = ctx.guild.get_channel(settings["channel"])
        channel = channel or ctx.channel
        if not channel.permissions_for(ctx.me).create_instant_invite:
            raise commands.BotMissingPermissions(["create_instant_invite"])
        if not channel.permissions_for(ctx.author).create_instant_invite:
            raise commands.MissingPermissions(["create_instant_invite"])
        if days is None:
            days = settings["days"]
        if uses is None:
            if days:
                uses = settings["uses"]
            else:
                uses = settings["uses"] or 1
        generated = []
        for i in range(amount or 1):
            generated.append(await channel.create_invite(
                max_age=(days or 0) * 86400,
                max_uses=uses,
                temporary=False,
                unique=True,
                reason=get_audit_reason(ctx.author, reason=reason),
            ))
        await ctx.send("\n".join(invite.url for invite in generated),
                       delete_after=120)
Пример #2
0
    async def logsfrom(
        self,
        ctx,
        after: Optional[discord.PartialMessage] = None,
        before: Optional[discord.PartialMessage] = None,
        *,
        channel: discord.TextChannel = None,
    ):
        """
        Logs the specified channel into a file, then uploads the file.

        The channel will default to the current channel if none is specified.
        The limit may be the number of messages to log or the ID of the message to start after, exclusive.
        All timestamps are in UTC.
        """
        if channel:
            ctxc = copy(ctx)
            ctxc.channel = channel
        else:
            channel = ctx.channel
            ctxc = ctx
        if not channel.permissions_for(ctx.me).read_message_history:
            raise commands.BotMissingPermissions(["read_message_history"])
        if not await check_permissions(ctxc, {"read_message_history": True}):
            raise commands.MissingPermissions(["read_message_history"])
        after, before = getattr(after, "id",
                                after), getattr(before, "id", before)
        cancel_task = asyncio.ensure_future(
            ctx.bot.wait_for("message", check=MessagePredicate.cancelled(ctx)))
        async with ctx.typing():
            kwargs = {"oldest_first": False}
            if not after and not before:
                kwargs["limit"] = 100
            elif not before:
                kwargs.update(after=discord.Object(id=after), limit=after)
            elif not after:
                raise RuntimeError("This should never happen.")
            else:
                before = min((ctx.message.id, before))
                # TODO: wtf should this shit even *mean*
                if after >= before:
                    kwargs.update(after=discord.Object(id=after),
                                  limit=before,
                                  oldest_first=True)
                else:
                    kwargs.update(
                        after=discord.Object(id=after),
                        before=discord.Object(id=before),
                        limit=min((before, after)),
                    )
            print(kwargs)
            stream = io.BytesIO()
            last_h = MHeaders(None, None, None)
            message_task = asyncio.ensure_future(history(channel, **kwargs))
            done, _ = await asyncio.wait((cancel_task, message_task),
                                         return_when=asyncio.FIRST_COMPLETED)
            if cancel_task in done:
                message_task.cancel()
                return await ctx.send(_T("Okay, I've cancelled my logging."))
            messages = message_task.result()
            processed = 0
            pop = messages.popleft if kwargs["oldest_first"] else messages.pop
            while messages:
                await asyncio.sleep(0)
                if cancel_task.done():
                    return await ctx.send(
                        _T("Okay, I've cancelled my logging."))
                message = pop()
                now_h = MHeaders(message.author, message.created_at,
                                 message.edited_at)
                headers = now_h.to_str(last_h)
                last_h = now_h
                if headers:
                    stream.write(headers.encode("utf-8"))
                stream.write(message.clean_content.encode("utf-8"))
                if message.attachments:
                    stream.write(b"\n")
                    stream.write("; ".join(
                        f"[{a.filename}]({a.url})"
                        for a in message.attachments).encode("utf-8"))
                stream.write(b"\n")
                processed += 1
            cancel_task.cancel()
            stream.seek(0)
            return await ctx.send(
                content=_T("{} message{s} logged.").format(
                    processed, s=("" if processed == 1 else "s")),
                file=discord.File(stream, filename=f"{channel.name}.md"),
                delete_after=300,
            )