예제 #1
0
async def split_and_send_embed(
    message: str,
    channel: discord.abc.Messageable,
    use_uniform: bool = True,
    requesting_user: Optional[Union[discord.User, discord.Member]] = None,
    **kwargs,
):
    if not use_uniform and requesting_user is not None:
        raise ValueError("requesting_user argument is only valid if use_inform is True")

    async with channel.typing():
        embeds = []

        if use_uniform:
            for chunk in split_message(
                message,
                character_limit=6000 - len(uniform_embed(requesting_user, **kwargs)),
            ):
                embeds.append(
                    uniform_embed(requesting_user, description=chunk, **kwargs)
                )
        else:
            for chunk in split_message(
                message, character_limit=6000 - len(discord.Embed(**kwargs))
            ):
                embeds.append(discord.Embed(**kwargs))

        for embed in embeds:
            await channel.send(embed=embed)
예제 #2
0
async def purge_ids(
    channel: discord.abc.Messageable,
    ids: Iterable[int],
    now: Union[datetime, discord.abc.Snowflake],
):
    channel = await channel._get_channel()
    assert isinstance(channel, (discord.TextChannel, discord.DMChannel))
    try:
        nowdt: datetime = now.created_at  # type: ignore
    except AttributeError:
        assert isinstance(now, datetime)
        nowdt = now
    snowflakes = [
        channel.get_partial_message(i) for i in ids if nowdt -
        discord.utils.snowflake_time(i) < timedelta(days=14, minutes=-5)
    ]
    if not snowflakes:
        return
    try:
        can_purge = channel.permissions_for(
            channel.guild.me).manage_messages  # type: ignore
    except AttributeError:
        can_purge = False
    if can_purge:
        assert isinstance(channel, discord.TextChannel)
        while True:
            try:
                await channel.delete_messages(snowflakes[:100])  # type: ignore
            except discord.Forbidden:
                return
            except discord.HTTPException:
                pass
            snowflakes = snowflakes[100:]
            if snowflakes:
                await asyncio.sleep(1.5)
            else:
                return
    else:
        for partial in snowflakes:
            try:
                await partial.delete()
            except discord.Forbidden:
                return
            except discord.HTTPException:
                pass
예제 #3
0
async def type_message(destination: discord.abc.Messageable, content: str,
                       **kwargs) -> discord.Message:
    """Simulate typing and sending a message to a destination.
        Will send a typing indicator, wait a variable amount of time based on the length
        of the text (to simulate typing speed), then send the message.
        """
    content = common_filters.filter_urls(content)
    try:
        async with destination.typing():
            await asyncio.sleep(max(0.25, min(2.5, len(content) * 0.01)))
            return await destination.send(content=content, **kwargs)
    except discord.HTTPException:
        pass
예제 #4
0
    async def send_ooc_message(self, messageable: discord.abc.Messageable):
        ooc_channel = self.bot.get_channel(self.channel_id)
        if not ooc_channel:
            return await messageable.send(
                'Could not find out of context channel')

        if len(self.attachments) == 0:
            return await messageable.send('No images to send')

        async with messageable.typing():
            random_attachment = random.choice(self.attachments)
            attachment_file = await random_attachment.to_file()
            await messageable.send(file=attachment_file)
예제 #5
0
async def type_message(destination: discord.abc.Messageable, content: str,
                       **kwargs) -> discord.Message:
    """Simulate typing and sending a message to a destination.

    Will send a typing indicator, wait a variable amount of time based on the length
    of the text (to simulate typing speed), then send the message.
    """
    content = common_filters.filter_mass_mentions(content)
    content = common_filters.filter_urls(content)
    content = common_filters.filter_various_mentions(content)
    try:
        async with destination.typing():
            await asyncio.sleep(len(content) * 0.01)
            return await destination.send(content=content, **kwargs)
    except discord.HTTPException:
        pass  # Not allowed to send messages to this destination (or, sending the message failed)
예제 #6
0
    async def _create_quote_embed(
            self, msg: discord.Message,
            destination: discord.abc.Messageable) -> discord.Embed:
        destination_guild_id = getattr(getattr(destination, "guild", None),
                                       "id", None)
        embed = discord.Embed(
            description=msg.content if getattr(msg.guild, "id", None)
            == destination_guild_id else msg.clean_content,
            color=msg.author.color.value or discord.Embed.Empty,
            timestamp=msg.created_at,
        )
        embed.set_author(name=str(msg.author),
                         url=msg.jump_url,
                         icon_url=getattr(msg.author.avatar, "url",
                                          DEFAULT_AVATAR_URL))

        # TODO: embed images from imgur, Gyazo, etc.
        if msg.attachments:
            if (not isinstance(
                    msg.channel,
                (discord.abc.PrivateChannel, discord.PartialMessageable))
                    and msg.channel.is_nsfw()
                    and (isinstance(destination,
                                    (discord.abc.PrivateChannel,
                                     discord.PartialMessageable, discord.User))
                         or not destination.is_nsfw())):
                embed.add_field(
                    name=
                    f"{await self.localize('QUOTE_quote_attachments', destination_guild_id)}",
                    value=
                    f":underage: {await self.localize('QUOTE_quote_nonsfw', destination_guild_id)}",
                )
            elif len(msg.attachments) == 1 and (
                    url := msg.attachments[0].url).lower().endswith(
                        (".jpg", ".jpeg", ".jfif", ".png", ".gif", ".gifv",
                         ".webp", ".bmp", ".svg", ".tiff")):
                embed.set_image(url=url)
            else:
                embed.add_field(
                    name=
                    f"{await self.localize('QUOTE_quote_attachments', destination_guild_id)}",
                    value="\n".join(
                        f"[{attachment.filename}]({attachment.url})"
                        for attachment in msg.attachments),
                )
async def long_send(channel: discord.abc.Messageable,
                    message: str,
                    quotes=False,
                    cut_on_new_line=True,
                    embed=False,
                    **kwargs) -> Optional[Message]:
    """Send multiples messages for long contents. Returns the last message sent if one."""
    if cut_on_new_line:
        messages = _split_on_new_lines_message(message, quotes)
    else:
        messages = _split_message(message, quotes)
    if embed and (isinstance(channel, TextChannel)
                  and channel.permissions_for(channel.guild.me).embed_links):
        return await _send_embed(channel, messages, **kwargs)
    else:
        res = None
        for msg in messages:
            res = await channel.send(msg)
        return res
예제 #8
0
    async def send_notification(
            self,
            destination: discord.abc.Messageable,
            description: str,
            *,
            title: str = None,
            fields: list = [],
            footer: str = None,
            thumbnail: str = None,
            ping=False,
            file: discord.File = None,
            react: str = None,
            jump_to: discord.Message = None,
            allow_everyone_ping=False,
            force_text_only=False,
            heat_key: str = None,
            no_repeat_for: datetime.timedelta = None,
            quick_action: QuickAction = None) -> Optional[discord.Message]:
        """Sends a notification to the staff channel if a guild is passed. Embed preference is respected."""
        if no_repeat_for:
            if isinstance(destination, discord.Guild):
                guild = destination
            else:
                guild = destination.guild

            if not heat_key:  # A custom heat_key can be passed to block dynamic content
                heat_key = f"{destination.id}-{description}-{fields}"
                heat_key = f"core-notif-{crc32(heat_key.encode('utf-8', 'ignore'))}"

            if not heat.get_custom_heat(guild, heat_key) == 0:
                return
            heat.increase_custom_heat(guild, heat_key, no_repeat_for)

        guild = destination
        is_staff_notification = False
        if isinstance(destination, discord.Guild):
            is_staff_notification = True
            notify_channel_id = await self.config.guild(destination
                                                        ).notify_channel()
            destination = destination.get_channel(notify_channel_id)
            if destination is None:
                return

        staff_mention = ""
        if ping and is_staff_notification:
            staff_mention = f"<@&{await self.config.guild(guild).notify_role()}> "

        embed = None
        send_embed = await self.bot.embed_requested(destination, None)
        if send_embed is True and force_text_only is False:
            if jump_to:
                description += f"\n[Click to jump]({jump_to.jump_url})"
            embed = discord.Embed(
                title=title if title else "",
                description=description,
            )
            if footer: embed.set_footer(text=footer)
            if thumbnail: embed.set_thumbnail(url=thumbnail)
            for field in fields:
                embed.add_field(**field)
            message_content = staff_mention
            embed.color = await self.bot.get_embed_color(destination)
            embed.timestamp = utcnow()
        else:
            title = f"**{title}\n**" if title else ""
            footer = f"\n*{footer}*" if footer else ""
            fields_txt = ""
            for field in fields:
                fields_txt += f"\n**{field['name']}**: {field['value']}"
            jump_to = f"\n{jump_to.jump_url}" if jump_to else ""
            message_content = f"{title}{staff_mention}{description}{fields_txt}{jump_to}{footer}"

        allowed_mentions = discord.AllowedMentions(
            roles=True, everyone=allow_everyone_ping)
        msg = await destination.send(message_content,
                                     file=file,
                                     embed=embed,
                                     allowed_mentions=allowed_mentions)
        if react:
            await msg.add_reaction(react)

        if quick_action and is_staff_notification:
            self.quick_actions[guild.id][msg.id] = quick_action

        return msg