Example #1
0
    async def auto_poster_loop(self) -> None:
        """Post the top 5 posts daily, and the top 5 posts weekly."""
        # once we upgrade to d.py 1.3 this can be removed and the loop can use the `time=datetime.time.min` parameter
        now = datetime.utcnow()
        tomorrow = now + timedelta(days=1)
        midnight_tomorrow = tomorrow.replace(hour=0, minute=0, second=0)
        seconds_until = (midnight_tomorrow - now).total_seconds()

        await asyncio.sleep(seconds_until)

        await self.bot.wait_until_guild_available()
        if not self.webhook:
            await self.bot.fetch_webhook(Webhooks.reddit)

        if datetime.utcnow().weekday() == 0:
            await self.top_weekly_posts()
            # if it's a monday send the top weekly posts

        for subreddit in RedditConfig.subreddits:
            top_posts = await self.get_top_posts(subreddit=subreddit, time="day")
            username = sub_clyde(f"{subreddit} Top Daily Posts")
            message = await self.webhook.send(username=username, embed=top_posts, wait=True)

            if message.channel.is_news():
                await message.publish()
Example #2
0
    async def send_message_link_embeds(
        self,
        webhook_embed_list: list,
        message: discord.Message,
        webhook: discord.Webhook,
    ) -> Optional[int]:
        """
        Send message link embeds to #incidents channel.

        Using the `webhook` passed in as a parameter to send
        the embeds in the `webhook_embed_list` parameter.

        After sending each embed it maps the `message.id`
        to the `webhook_msg_ids` IDs in the async redis-cache.
        """
        try:
            webhook_msg = await webhook.send(
                embeds=[embed for embed in webhook_embed_list if embed],
                username=sub_clyde(message.author.name),
                avatar_url=message.author.display_avatar.url,
                wait=True,
            )
        except discord.DiscordException:
            log.exception(
                f"Failed to send message link embed {message.id} to #incidents."
            )
        else:
            await self.message_link_embeds_cache.set(message.id,
                                                     webhook_msg.id)
            log.trace("Message link embeds sent successfully to #incidents!")
            return webhook_msg.id
Example #3
0
File: reddit.py Project: pormes/bot
    async def top_weekly_posts(self) -> None:
        """Post a summary of the top posts."""
        for subreddit in RedditConfig.subreddits:
            # Send and pin the new weekly posts.
            top_posts = await self.get_top_posts(subreddit=subreddit,
                                                 time="week")
            username = sub_clyde(f"{subreddit} Top Weekly Posts")
            message = await self.webhook.send(wait=True,
                                              username=username,
                                              embed=top_posts)

            if subreddit.lower() == "r/python":
                if not self.channel:
                    log.warning(
                        "Failed to get #reddit channel to remove pins in the weekly loop."
                    )
                    return

                # Remove the oldest pins so that only 12 remain at most.
                pins = await self.channel.pins()

                while len(pins) >= 12:
                    await pins[-1].unpin()
                    del pins[-1]

                await message.pin()

                if message.channel.is_news():
                    await message.publish()
Example #4
0
 async def send_webhook(
     self,
     content: Optional[str] = None,
     username: Optional[str] = None,
     avatar_url: Optional[str] = None,
     embed: Optional[Embed] = None,
 ) -> None:
     """Send a webhook to the duck_pond channel."""
     try:
         await self.webhook.send(content=content,
                                 username=sub_clyde(username),
                                 avatar_url=avatar_url,
                                 embed=embed)
     except discord.HTTPException:
         log.exception("Failed to send a message to the Duck Pool webhook")
Example #5
0
 async def webhook_send(
     self,
     content: Optional[str] = None,
     username: Optional[str] = None,
     avatar_url: Optional[str] = None,
     embed: Optional[Embed] = None,
 ) -> None:
     """Sends a message to the webhook with the specified kwargs."""
     username = messages.sub_clyde(username)
     try:
         await self.webhook.send(content=content, username=username, avatar_url=avatar_url, embed=embed)
     except discord.HTTPException as exc:
         self.log.exception(
             "Failed to send a message to the webhook",
             exc_info=exc
         )
Example #6
0
    async def archive(self, incident: discord.Message, outcome: Signal,
                      actioned_by: discord.Member) -> bool:
        """
        Relay an embed representation of `incident` to the #incidents-archive channel.

        The following pieces of information are relayed:
            * Incident message content (as embed description)
            * Incident attachment (if image, shown in archive embed)
            * Incident author name (as webhook author)
            * Incident author avatar (as webhook avatar)
            * Resolution signal `outcome` (as embed colour & footer)
            * Moderator `actioned_by` (name & discriminator shown in footer)

        If `incident` contains an attachment, we try to add it to the archive embed. There is
        no handing of extensions / file types - we simply dispatch the attachment file with the
        webhook, and try to display it in the embed. Testing indicates that if the attachment
        cannot be displayed (e.g. a text file), it's invisible in the embed, with no error.

        Return True if the relay finishes successfully. If anything goes wrong, meaning
        not all information was relayed, return False. This signals that the original
        message is not safe to be deleted, as we will lose some information.
        """
        log.info(
            f"Archiving incident: {incident.id} (outcome: {outcome}, actioned by: {actioned_by})"
        )
        embed, attachment_file = await make_embed(incident, outcome,
                                                  actioned_by)

        try:
            webhook = await self.bot.fetch_webhook(Webhooks.incidents_archive)
            await webhook.send(
                embed=embed,
                username=sub_clyde(incident.author.name),
                avatar_url=incident.author.avatar_url,
                file=attachment_file,
            )
        except Exception:
            log.exception(
                f"Failed to archive incident {incident.id} to #incidents-archive"
            )
            return False
        else:
            log.trace("Message archived successfully!")
            return True
Example #7
0
    def test_sub_clyde(self):
        """Uppercase E's and lowercase e's are substituted with their cyrillic counterparts."""
        sub_e = "\u0435"
        sub_E = "\u0415"  # noqa: N806: Uppercase E in variable name

        test_cases = (
            (None, None),
            ("", ""),
            ("clyde", f"clyd{sub_e}"),
            ("CLYDE", f"CLYD{sub_E}"),
            ("cLyDe", f"cLyD{sub_e}"),
            ("BIGclyde", f"BIGclyd{sub_e}"),
            ("small clydeus the unholy", f"small clyd{sub_e}us the unholy"),
            ("BIGCLYDE, babyclyde", f"BIGCLYD{sub_E}, babyclyd{sub_e}"),
        )

        for username_in, username_out in test_cases:
            with self.subTest(input=username_in, expected_output=username_out):
                self.assertEqual(messages.sub_clyde(username_in), username_out)
Example #8
0
async def send_webhook(webhook: discord.Webhook,
                       content: Optional[str] = None,
                       username: Optional[str] = None,
                       avatar_url: Optional[str] = None,
                       embed: Optional[Embed] = None,
                       wait: Optional[bool] = False) -> discord.Message:
    """
    Send a message using the provided webhook.

    This uses sub_clyde() and tries for an HTTPException to ensure it doesn't crash.
    """
    try:
        return await webhook.send(
            content=content,
            username=sub_clyde(username),
            avatar_url=avatar_url,
            embed=embed,
            wait=wait,
        )
    except discord.HTTPException:
        log.exception("Failed to send a message to the webhook!")