Example #1
0
    async def send(
        self,
        message: discord.Message,
        destination: typing.Union[discord.TextChannel, discord.DMChannel,
                                  discord.User, discord.Member] = None,
        from_mod: bool = False,
        note: bool = False,
        anonymous: bool = False,
        plain: bool = False,
        persistent_note: bool = False,
        thread_creation: bool = False,
    ) -> None:

        self.bot.loop.create_task(
            self._restart_close_timer())  # Start or restart thread auto close

        if self.close_task is not None:
            # cancel closing if a thread message is sent.
            self.bot.loop.create_task(self.cancel_closure())
            self.bot.loop.create_task(
                self.channel.send(embed=discord.Embed(
                    color=self.bot.error_color,
                    description="Scheduled close has been cancelled! ❌",
                )))

        if not self.ready:
            await self.wait_until_ready()

        if not from_mod and not note:
            self.bot.loop.create_task(
                self.bot.api.append_log(message, channel_id=self.channel.id))

        destination = destination or self.channel

        author = message.author

        embed = discord.Embed(description=message.content)
        if self.bot.config["show_timestamp"]:
            embed.timestamp = message.created_at

        system_avatar_url = "https://cdn.discordapp.com/attachments/809115390385848340/822195746572861480/pol-wumpus.png"

        if not note:
            if anonymous and from_mod and not isinstance(
                    destination, discord.TextChannel):
                # Anonymously sending to the user.
                tag = self.bot.config["mod_tag"]
                if tag is None:
                    tag = str(author.top_role)
                name = self.bot.config["anon_username"]
                if name is None:
                    name = tag
                avatar_url = self.bot.config["anon_avatar_url"]
                if avatar_url is None:
                    avatar_url = self.bot.guild.icon_url
                embed.set_author(
                    name=name,
                    icon_url=avatar_url,
                    url=
                    f"https://discordapp.com/channels/{self.bot.guild.id}#{message.id}",
                )
            else:
                # Normal message
                name = str(author)
                avatar_url = author.avatar_url
                embed.set_author(
                    name=name,
                    icon_url=avatar_url,
                    url=
                    f"https://discordapp.com/users/{author.id}#{message.id}",
                )
        else:
            # Special note messages
            embed.set_author(
                name=
                f"{'Persistent' if persistent_note else ''} Note ({author.name})",
                icon_url=system_avatar_url,
                url=f"https://discordapp.com/users/{author.id}#{message.id}",
            )

        ext = [(a.url, a.filename, False) for a in message.attachments]

        images = []
        attachments = []
        for attachment in ext:
            if is_image_url(attachment[0]):
                images.append(attachment)
            else:
                attachments.append(attachment)

        image_urls = re.findall(
            r"http[s]?:\/\/(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*(),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+",
            message.content,
        )

        image_urls = [(is_image_url(url, convert_size=False), None, False)
                      for url in image_urls
                      if is_image_url(url, convert_size=False)]
        images.extend(image_urls)
        images.extend((
            str(i.image_url) if isinstance(i.image_url, discord.Asset) else i.
            image_url,
            f"{i.name} Sticker",
            True,
        ) for i in message.stickers)

        embedded_image = False

        prioritize_uploads = any(i[1] is not None for i in images)

        additional_images = []
        additional_count = 1

        for url, filename, is_sticker in images:
            if (not prioritize_uploads or
                ((url is None or is_image_url(url))
                 and filename)) and not embedded_image:
                if url is not None:
                    embed.set_image(url=url)
                if filename:
                    if is_sticker:
                        if url is None:
                            description = "Unable to retrieve sticker image"
                        else:
                            description = "\u200b"
                        embed.add_field(name=filename, value=description)
                    else:
                        embed.add_field(name="Image",
                                        value=f"[{filename}]({url})")
                embedded_image = True
            else:
                if note:
                    color = self.bot.main_color
                elif from_mod:
                    color = self.bot.mod_color
                else:
                    color = self.bot.recipient_color

                img_embed = discord.Embed(color=color)

                if url is not None:
                    img_embed.set_image(url=url)
                    img_embed.url = url
                if filename is not None:
                    img_embed.title = filename
                img_embed.set_footer(
                    text=f"Additional Image Upload ({additional_count})")
                img_embed.timestamp = message.created_at
                additional_images.append(destination.send(embed=img_embed))
                additional_count += 1

        file_upload_count = 1

        for url, filename, _ in attachments:
            embed.add_field(name=f"File upload ({file_upload_count})",
                            value=f"[{filename}]({url})")
            file_upload_count += 1

        if from_mod:
            embed.colour = self.bot.mod_color
            # Anonymous reply sent in thread channel
            if anonymous and isinstance(destination, discord.TextChannel):
                embed.set_footer(text="Anonymous Reply - Staff")
            # Normal messages
            elif not anonymous:
                mod_tag = self.bot.config["mod_tag"]
                if mod_tag is None:
                    mod_tag = str(message.author.top_role)
                embed.set_footer(text=mod_tag)  # Normal messages
            else:
                embed.set_footer(text=self.bot.config["anon_tag"])
        elif note:
            embed.colour = self.bot.main_color
        else:
            embed.set_footer(text="User")
            embed.colour = self.bot.recipient_color

        if (from_mod or note) and not thread_creation:
            delete_message = not bool(message.attachments)
            if delete_message and destination == self.channel:
                try:
                    await message.delete()
                except Exception as e:
                    logger.warning("Cannot delete message: %s.", e)

        if (from_mod
                and self.bot.config["dm_disabled"] == DMDisabled.ALL_THREADS
                and destination != self.channel):
            logger.info("Sending a message to %s when DM disabled is set.",
                        self.recipient)

        try:
            await destination.trigger_typing()
        except discord.NotFound:
            logger.warning("Channel not found.")
            raise

        if not from_mod and not note:
            mentions = self.get_notifications()
        else:
            mentions = None

        if plain:
            if from_mod and not isinstance(destination, discord.TextChannel):
                # Plain to user
                if embed.footer.text:
                    plain_message = f"**({embed.footer.text}) "
                else:
                    plain_message = "**"
                plain_message += f"{embed.author.name}:** {embed.description}"
                files = []
                for i in embed.fields:
                    if "Image" in i.name:
                        async with self.bot.session.get(
                                i.field[i.field.find("http"):-1]) as resp:
                            stream = io.BytesIO(await resp.read())
                            files.append(discord.File(stream))

                msg = await destination.send(plain_message, files=files)
            else:
                # Plain to mods
                embed.set_footer(text="[Plain Message] " + embed.footer.text)
                msg = await destination.send(mentions, embed=embed)

        else:
            msg = await destination.send(mentions, embed=embed)

        if additional_images:
            self.ready = False
            await asyncio.gather(*additional_images)
            self.ready = True

        return msg
Example #2
0
    async def send(self,
                   message,
                   destination=None,
                   from_mod=False,
                   note=False,
                   anonymous=False):
        if self.close_task is not None:
            # cancel closing if a thread message is sent.
            await self.cancel_closure()
            await self.channel.send(embed=discord.Embed(
                color=discord.Color.red(),
                description='Scheduled close has been cancelled.'))

        if not from_mod and not note:
            await self.bot.api.append_log(message, self.channel.id)

        if not self.ready:
            await self.wait_until_ready()

        destination = destination or self.channel

        author = message.author

        embed = discord.Embed(description=message.content,
                              timestamp=message.created_at)

        system_avatar_url = 'https://discordapp.com/assets/' \
                            'f78426a064bc9dd24847519259bc42af.png'

        if not note:
            if anonymous and from_mod and \
                    not isinstance(destination, discord.TextChannel):
                # Anonymously sending to the user.
                tag = self.bot.config.get('mod_tag',
                                          str(message.author.top_role))
                name = self.bot.config.get('anon_username', tag)
                avatar_url = self.bot.config.get('anon_avatar_url',
                                                 self.bot.guild.icon_url)
            else:
                # Normal message
                name = str(author)
                avatar_url = author.avatar_url

            embed.set_author(name=name,
                             icon_url=avatar_url,
                             url=message.jump_url)
        else:
            # Special note messages
            embed.set_author(name=f'Note ({author.name})',
                             icon_url=system_avatar_url,
                             url=message.jump_url)

        delete_message = not bool(message.attachments)

        attachments = [(a.url, a.filename) for a in message.attachments]

        images = [x for x in attachments if is_image_url(*x)]
        attachments = [x for x in attachments if not is_image_url(*x)]

        image_links = [
            (link, None)
            for link in re.findall(r'(https?://[^\s]+)', message.content)
        ]
        image_links = [x for x in image_links if is_image_url(*x)]
        images.extend(image_links)

        embedded_image = False

        prioritize_uploads = any(i[1] is not None for i in images)

        additional_images = []
        additional_count = 1

        for att in images:  # TODO: Logic needs review
            if not prioritize_uploads or (is_image_url(*att)
                                          and not embedded_image and att[1]):
                embed.set_image(url=att[0])
                embedded_image = True
            elif att[1] is not None:
                if note:
                    color = discord.Color.blurple()
                elif from_mod:
                    color = self.bot.mod_color
                else:
                    color = self.bot.recipient_color

                img_embed = discord.Embed(color=color)
                img_embed.set_image(url=att[0])
                img_embed.set_footer(
                    text=f'Additional Image Upload ({additional_count})')
                img_embed.timestamp = message.created_at
                additional_images.append(destination.send(embed=img_embed))
                additional_count += 1

        file_upload_count = 1

        for att in attachments:
            embed.add_field(name=f'File upload ({file_upload_count})',
                            value=f'[{att[1]}]({att[0]})')
            file_upload_count += 1

        if from_mod:
            # noinspection PyUnresolvedReferences,PyDunderSlots
            embed.color = self.bot.mod_color  # pylint: disable=E0237
            # Anonymous reply sent in thread channel
            if anonymous and isinstance(destination, discord.TextChannel):
                embed.set_footer(text='Anonymous Reply')
            # Normal messages
            elif not anonymous:
                tag = self.bot.config.get('mod_tag',
                                          str(message.author.top_role))
                embed.set_footer(text=tag)  # Normal messages
            else:
                embed.set_footer(
                    text=self.bot.config.get('anon_tag', 'Response'))
        elif note:
            # noinspection PyUnresolvedReferences,PyDunderSlots
            embed.color = discord.Color.blurple()  # pylint: disable=E0237
        else:
            embed.set_footer(text=f'Recipient')
            # noinspection PyUnresolvedReferences,PyDunderSlots
            embed.color = self.bot.recipient_color  # pylint: disable=E0237

        await destination.trigger_typing()

        if not from_mod:
            mentions = self.get_notifications()
        else:
            mentions = None

        await destination.send(mentions, embed=embed)

        if additional_images:
            self.ready = False
            await asyncio.gather(*additional_images)
            self.ready = True

        if delete_message:
            try:
                await message.delete()
            except discord.HTTPException:
                pass
Example #3
0
    async def send(
        self,
        message: discord.Message,
        destination: typing.Union[discord.TextChannel, discord.DMChannel,
                                  discord.User, discord.Member] = None,
        from_mod: bool = False,
        note: bool = False,
        anonymous: bool = False,
    ) -> None:

        self.bot.loop.create_task(
            self._restart_close_timer())  # Start or restart thread auto close

        if self.close_task is not None:
            # cancel closing if a thread message is sent.
            self.bot.loop.create_task(self.cancel_closure())
            self.bot.loop.create_task(
                self.channel.send(embed=discord.Embed(
                    color=self.bot.error_color,
                    description="Se canceló el cierre programado.",
                )))

        if not self.ready:
            await self.wait_until_ready()

        if not from_mod and not note:
            self.bot.loop.create_task(
                self.bot.api.append_log(message, channel_id=self.channel.id))

        destination = destination or self.channel

        author = message.author

        embed = discord.Embed(description=message.content,
                              timestamp=message.created_at)

        system_avatar_url = "https://discordapp.com/assets/f78426a064bc9dd24847519259bc42af.png"

        if not note:
            if anonymous and from_mod and not isinstance(
                    destination, discord.TextChannel):
                # Anonymously sending to the user.
                tag = self.bot.config["mod_tag"]
                if tag is None:
                    tag = str(author.top_role)
                name = self.bot.config["anon_username"]
                if name is None:
                    name = tag
                avatar_url = self.bot.config["anon_avatar_url"]
                if avatar_url is None:
                    avatar_url = self.bot.guild.icon_url
                embed.set_author(
                    name=name,
                    icon_url=avatar_url,
                    url=
                    f"https://discordapp.com/channels/{self.bot.guild.id}#{message.id}",
                )
            else:
                # Normal message
                name = str(author)
                avatar_url = author.avatar_url
                embed.set_author(
                    name=name,
                    icon_url=avatar_url,
                    url=
                    f"https://discordapp.com/users/{author.id}#{message.id}",
                )
        else:
            # Special note messages
            embed.set_author(
                name=f"Note ({author.name})",
                icon_url=system_avatar_url,
                url=f"https://discordapp.com/users/{author.id}#{message.id}",
            )

        ext = [(a.url, a.filename) for a in message.attachments]

        images = []
        attachments = []
        for attachment in ext:
            if is_image_url(attachment[0]):
                images.append(attachment)
            else:
                attachments.append(attachment)

        image_urls = re.findall(
            r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*(),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+",
            message.content,
        )

        image_urls = [(url, None) for url in image_urls if is_image_url(url)]
        images.extend(image_urls)

        embedded_image = False

        prioritize_uploads = any(i[1] is not None for i in images)

        additional_images = []
        additional_count = 1

        for url, filename in images:
            if not prioritize_uploads or (is_image_url(url)
                                          and not embedded_image and filename):
                embed.set_image(url=url)
                if filename:
                    embed.add_field(name="Image", value=f"[{filename}]({url})")
                embedded_image = True
            elif filename is not None:
                if note:
                    color = self.bot.main_color
                elif from_mod:
                    color = self.bot.mod_color
                else:
                    color = self.bot.recipient_color

                img_embed = discord.Embed(color=color)
                img_embed.set_image(url=url)
                img_embed.title = filename
                img_embed.url = url
                img_embed.set_footer(
                    text=f"Additional Image Upload ({additional_count})")
                img_embed.timestamp = message.created_at
                additional_images.append(destination.send(embed=img_embed))
                additional_count += 1

        file_upload_count = 1

        for url, filename in attachments:
            embed.add_field(name=f"File upload ({file_upload_count})",
                            value=f"[{filename}]({url})")
            file_upload_count += 1

        if from_mod:
            embed.colour = self.bot.mod_color
            # Anonymous reply sent in thread channel
            if anonymous and isinstance(destination, discord.TextChannel):
                embed.set_footer(text="Anonymous Reply")
            # Normal messages
            elif not anonymous:
                mod_tag = self.bot.config["mod_tag"]
                if mod_tag is None:
                    mod_tag = str(message.author.top_role)
                embed.set_footer(text=mod_tag)  # Normal messages
            else:
                embed.set_footer(text=self.bot.config["anon_tag"])
        elif note:
            embed.colour = self.bot.main_color
        else:
            embed.set_footer(text=f"Message ID: {message.id}")
            embed.colour = self.bot.recipient_color

        if from_mod or note:
            delete_message = not bool(message.attachments)
            if delete_message and destination == self.channel:
                try:
                    await message.delete()
                except Exception as e:
                    logger.warning("Cannot delete message: %s.", e)

        if from_mod and self.bot.config[
                "dm_disabled"] == 2 and destination != self.channel:
            logger.info("Sending a message to %s when DM disabled is set.",
                        self.recipient)

        try:
            await destination.trigger_typing()
        except discord.NotFound:
            logger.warning("Channel not found.")
            raise

        if not from_mod and not note:
            mentions = self.get_notifications()
        else:
            mentions = None

        msg = await destination.send(mentions, embed=embed)

        if additional_images:
            self.ready = False
            await asyncio.gather(*additional_images)
            self.ready = True

        return msg
Example #4
0
    async def send(
        self,
        message: discord.Message,
        destination: typing.Union[discord.TextChannel, discord.DMChannel,
                                  discord.User, discord.Member] = None,
        from_mod: bool = False,
        note: bool = False,
        anonymous: bool = False,
    ) -> None:
        if self.close_task is not None:
            # cancel closing if a thread message is sent.
            self.bot.loop.create_task(self.cancel_closure())
            self.bot.loop.create_task(
                self.channel.send(embed=discord.Embed(
                    color=discord.Color.red(),
                    description="Scheduled close has been cancelled.",
                )))

        if not self.ready:
            await self.wait_until_ready()

        if not from_mod and not note:
            self.bot.loop.create_task(
                self.bot.api.append_log(message, self.channel.id))

        destination = destination or self.channel

        author = message.author

        embed = discord.Embed(description=message.content,
                              timestamp=message.created_at)

        system_avatar_url = (
            "https://discordapp.com/assets/f78426a064bc9dd24847519259bc42af.png"
        )

        if not note:
            if (anonymous and from_mod
                    and not isinstance(destination, discord.TextChannel)):
                # Anonymously sending to the user.
                tag = self.bot.config.get("mod_tag",
                                          str(message.author.top_role))
                name = self.bot.config.get("anon_username", tag)
                avatar_url = self.bot.config.get("anon_avatar_url",
                                                 self.bot.guild.icon_url)
            else:
                # Normal message
                name = str(author)
                avatar_url = author.avatar_url

            embed.set_author(name=name,
                             icon_url=avatar_url,
                             url=message.jump_url)
        else:
            # Special note messages
            embed.set_author(
                name=f"Note ({author.name})",
                icon_url=system_avatar_url,
                url=message.jump_url,
            )

        delete_message = not bool(message.attachments)

        attachments = [(a.url, a.filename) for a in message.attachments]

        images = [x for x in attachments if is_image_url(*x)]
        attachments = [x for x in attachments if not is_image_url(*x)]

        image_links = [(link, None) for link in re.findall(
            r"https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)",
            message.content,
        )]

        image_links = [x for x in image_links if is_image_url(*x)]
        images.extend(image_links)

        embedded_image = False

        prioritize_uploads = any(i[1] is not None for i in images)

        additional_images = []
        additional_count = 1

        for att in images:
            if not prioritize_uploads or (is_image_url(*att)
                                          and not embedded_image and att[1]):
                embed.set_image(url=att[0])
                if att[1]:
                    embed.add_field(name="Image",
                                    value=f"[{att[1]}]({att[0]})")
                embedded_image = True
            elif att[1] is not None:
                if note:
                    color = discord.Color.blurple()
                elif from_mod:
                    color = self.bot.mod_color
                else:
                    color = self.bot.recipient_color

                img_embed = discord.Embed(color=color)
                img_embed.set_image(url=att[0])
                img_embed.title = att[1]
                img_embed.url = att[0]
                img_embed.set_footer(
                    text=f"Additional Image Upload ({additional_count})")
                img_embed.timestamp = message.created_at
                additional_images.append(destination.send(embed=img_embed))
                additional_count += 1

        file_upload_count = 1

        for att in attachments:
            embed.add_field(name=f"File upload ({file_upload_count})",
                            value=f"[{att[1]}]({att[0]})")
            file_upload_count += 1

        if from_mod:
            # noinspection PyUnresolvedReferences,PyDunderSlots
            embed.color = self.bot.mod_color  # pylint: disable=E0237
            # Anonymous reply sent in thread channel
            if anonymous and isinstance(destination, discord.TextChannel):
                embed.set_footer(text="Anonymous Reply")
            # Normal messages
            elif not anonymous:
                tag = self.bot.config.get("mod_tag",
                                          str(message.author.top_role))
                embed.set_footer(text=tag)  # Normal messages
            else:
                embed.set_footer(
                    text=self.bot.config.get("anon_tag", "Response"))
        elif note:
            # noinspection PyUnresolvedReferences,PyDunderSlots
            embed.color = discord.Color.blurple()  # pylint: disable=E0237
        else:
            embed.set_footer(text=f"Recipient")
            # noinspection PyUnresolvedReferences,PyDunderSlots
            embed.color = self.bot.recipient_color  # pylint: disable=E0237

        await destination.trigger_typing()

        if not from_mod and not note:
            mentions = self.get_notifications()
        else:
            mentions = None

        _msg = await destination.send(mentions, embed=embed)

        if additional_images:
            self.ready = False
            await asyncio.gather(*additional_images)
            self.ready = True

        if delete_message:
            self.bot.loop.create_task(ignore(message.delete()))

        return _msg