From 428f459e98e25373dc9a136bbed51b5e570d253c Mon Sep 17 00:00:00 2001 From: corbz Date: Mon, 18 Dec 2023 01:06:45 +0000 Subject: [PATCH] cmd.py to rss.py + utils --- src/extensions/{cmd.py => rss.py} | 43 ++++++++++--------------------- src/utils.py | 31 ++++++++++++++++++++++ 2 files changed, 44 insertions(+), 30 deletions(-) rename src/extensions/{cmd.py => rss.py} (92%) create mode 100644 src/utils.py diff --git a/src/extensions/cmd.py b/src/extensions/rss.py similarity index 92% rename from src/extensions/cmd.py rename to src/extensions/rss.py index 220e449..2ab7bb7 100644 --- a/src/extensions/cmd.py +++ b/src/extensions/rss.py @@ -1,13 +1,12 @@ """ -Extension for the `CommandCog`. -Loading this file via `commands.Bot.load_extension` will add `CommandCog` to the bot. +Extension for the `RssCog`. +Loading this file via `commands.Bot.load_extension` will add `RssCog` to the bot. """ import logging import validators from typing import Tuple -import aiohttp import textwrap import feedparser from markdownify import markdownify @@ -16,6 +15,7 @@ from discord.ext import commands from discord.app_commands import Choice, Group, autocomplete, choices from sqlalchemy import insert, select, and_, delete +from utils import get_rss_data, followup, audit from feed import get_source, Source from db import DatabaseManager, SentArticleModel, RssSourceModel @@ -26,29 +26,6 @@ rss_list_sort_choices = [ Choice(name="Date Added", value=1) ] -async def get_rss_data(url: str): - async with aiohttp.ClientSession() as session: - async with session.get(url) as response: - items = await response.text(), response.status - - return items - -async def followup(inter: Interaction, *args, **kwargs): - """Shorthand for following up on an interaction. - - Parameters - ---------- - inter : Interaction - Represents an app command interaction. - """ - - await inter.followup.send(*args, **kwargs) - -async def audit(cog, *args, **kwargs): - """Shorthand for auditing an interaction.""" - - await cog.bot.audit(*args, **kwargs) - # TODO SECURITY: a potential attack is that the user submits an rss feed then changes the target resource. # Run a period task to check this. async def validate_rss_source(nickname: str, url: str) -> Tuple[str | None, feedparser.FeedParserDict | None]: @@ -93,7 +70,7 @@ async def validate_rss_source(nickname: str, url: str) -> Tuple[str | None, feed return None, feed -class CommandCog(commands.Cog): +class RssCog(commands.Cog): """ Command cog. """ @@ -318,6 +295,10 @@ class CommandCog(commands.Cog): source = Source.from_parsed(feed) articles = source.get_latest_articles(max) + if not articles: + await followup(inter, "Sorry, I couldn't find any articles from this feed.") + return + embeds = [] for article in articles: md_description = markdownify(article.description, strip=("img",)) @@ -330,8 +311,10 @@ class CommandCog(commands.Cog): timestamp=article.published, colour=Colour.brand_red() ) + thumbail_url = await article.get_thumbnail_url() + thumbail_url = thumbail_url if validators.url(thumbail_url) else None embed.set_thumbnail(url=source.icon_url) - embed.set_image(url=await article.get_thumbnail_url()) + embed.set_image(url=thumbail_url) embed.set_footer(text=article.author) embed.set_author( name=source.name, @@ -358,9 +341,9 @@ class CommandCog(commands.Cog): async def setup(bot): """ Setup function for this extension. - Adds `CommandCog` to the bot. + Adds `RssCog` to the bot. """ - cog = CommandCog(bot) + cog = RssCog(bot) await bot.add_cog(cog) log.info(f"Added {cog.__class__.__name__} cog") diff --git a/src/utils.py b/src/utils.py new file mode 100644 index 0000000..d0c14bb --- /dev/null +++ b/src/utils.py @@ -0,0 +1,31 @@ +"""A collection of utility functions that can be used in various places.""" + +import aiohttp +import logging + +from discord import Interaction + +log = logging.getLogger(__name__) + +async def get_rss_data(url: str): + async with aiohttp.ClientSession() as session: + async with session.get(url) as response: + items = await response.text(), response.status + + return items + +async def followup(inter: Interaction, *args, **kwargs): + """Shorthand for following up on an interaction. + + Parameters + ---------- + inter : Interaction + Represents an app command interaction. + """ + + await inter.followup.send(*args, **kwargs) + +async def audit(cog, *args, **kwargs): + """Shorthand for auditing an interaction.""" + + await cog.bot.audit(*args, **kwargs)