From b2ab72d4b069ce907a8f2107857c7086c0f383f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Hells=C3=A9n?= <tlovinator@gmail.com> Date: Tue, 17 Jan 2023 23:59:18 +0100 Subject: [PATCH] You can now customize the default message --- discord_rss_bot/custom_message.py | 30 ++++++++++++++++++++-- discord_rss_bot/feeds.py | 20 +++++++++------ discord_rss_bot/main.py | 37 ++++++++++++++++++++++----- discord_rss_bot/settings.py | 2 ++ discord_rss_bot/templates/custom.html | 7 ++--- 5 files changed, 76 insertions(+), 20 deletions(-) diff --git a/discord_rss_bot/custom_message.py b/discord_rss_bot/custom_message.py index e6197dd..b51d73c 100644 --- a/discord_rss_bot/custom_message.py +++ b/discord_rss_bot/custom_message.py @@ -1,9 +1,32 @@ +import re + from reader import Entry, Feed, Reader, TagNotFoundError from discord_rss_bot.custom_filters import convert_to_md from discord_rss_bot.settings import get_reader +def get_images_from_string(string: str) -> tuple[str, list[str]]: + """Get images from a string. This will also remove the images from the string. + + Args: + string: The string to get the images from. + + Returns: + Returns a list of images. + """ + # This regex will match any markdown image that follows the format of . + image_regex = r"!\[(.*)\]\((.*)\)" + + # Remove them from the string + new_string: str = re.sub(image_regex, "", string) + + # Get the images + images: list[str] = re.findall(image_regex, string) + + return new_string, images + + def try_to_replace(custom_message: str, template: str, replace_with: str) -> str: """Try to replace a tag in custom_message. @@ -26,7 +49,7 @@ def try_to_replace(custom_message: str, template: str, replace_with: str) -> str return custom_message -def replace_tags(feed: Feed, entry: Entry) -> str: +def replace_tags(feed: Feed, entry: Entry) -> tuple[str, list[str]]: """Replace tags in custom_message. Args: @@ -78,7 +101,10 @@ def replace_tags(feed: Feed, entry: Entry) -> str: for replacement in list_of_replacements: for template, replace_with in replacement.items(): custom_message = try_to_replace(custom_message, template, replace_with) - return custom_message + + custom_message, images = get_images_from_string(custom_message) + + return custom_message, images def get_custom_message(custom_reader: Reader, feed: Feed) -> str: diff --git a/discord_rss_bot/feeds.py b/discord_rss_bot/feeds.py index 448dec8..b4b5316 100644 --- a/discord_rss_bot/feeds.py +++ b/discord_rss_bot/feeds.py @@ -7,7 +7,7 @@ from requests import Response from discord_rss_bot import custom_message, settings from discord_rss_bot.filter.blacklist import should_be_skipped from discord_rss_bot.filter.whitelist import has_white_tags, should_be_sent -from discord_rss_bot.settings import get_reader +from discord_rss_bot.settings import default_custom_message, get_reader def send_to_discord(custom_reader: Reader | None = None, feed: Feed | None = None, do_once: bool = False) -> None: @@ -36,24 +36,28 @@ def send_to_discord(custom_reader: Reader | None = None, feed: Feed | None = Non else: entries = reader.get_entries(feed=feed, read=False) + # Loop through the unread entries. for entry in entries: # Set the webhook to read, so we don't send it again. reader.set_entry_read(entry, True) + # Get the webhook URL for the entry. If it is None, we will continue to the next entry. webhook_url: str = settings.get_webhook_for_entry(reader, entry) - - webhook_message: str = f"{entry.title}\n{entry.link}" - if not webhook_url: continue + # If the user has set the custom message to an empty string, we will use the default message, otherwise we will + # use the custom message. + if custom_message.get_custom_message(reader, entry.feed) != "": + webhook_message = custom_message.replace_tags(entry=entry, feed=entry.feed) # type: ignore + else: + webhook_message: str = default_custom_message + + # Create the webhook. webhook: DiscordWebhook = DiscordWebhook(url=webhook_url, content=webhook_message, rate_limit_retry=True) - if custom_message.get_custom_message(reader, entry.feed) != "": - webhook.content = custom_message.replace_tags(entry=entry, feed=entry.feed) - + # Check if the feed has a whitelist, and if it does, check if the entry is whitelisted. if feed is not None and has_white_tags(reader, feed): - # Only send the entry if it is whitelisted, otherwise, mark it as read and continue. if should_be_sent(reader, entry): response: Response = webhook.execute() reader.set_entry_read(entry, True) diff --git a/discord_rss_bot/main.py b/discord_rss_bot/main.py index 95ed7d8..3ab3a4b 100644 --- a/discord_rss_bot/main.py +++ b/discord_rss_bot/main.py @@ -11,13 +11,14 @@ from fastapi.templating import Jinja2Templates from reader import Entry, EntryCounts, EntrySearchCounts, EntrySearchResult, Feed, FeedCounts, Reader, TagNotFoundError from starlette.responses import RedirectResponse +from discord_rss_bot import settings from discord_rss_bot.custom_filters import convert_to_md, encode_url, entry_is_blacklisted, entry_is_whitelisted from discord_rss_bot.custom_message import get_custom_message from discord_rss_bot.feeds import send_to_discord from discord_rss_bot.filter.blacklist import get_blacklist_content, get_blacklist_summary, get_blacklist_title from discord_rss_bot.filter.whitelist import get_whitelist_content, get_whitelist_summary, get_whitelist_title from discord_rss_bot.search import create_html_for_search_results -from discord_rss_bot.settings import get_reader, list_webhooks +from discord_rss_bot.settings import default_custom_message, get_reader, list_webhooks app: FastAPI = FastAPI() app.mount("/static", StaticFiles(directory="discord_rss_bot/static"), name="static") @@ -142,9 +143,15 @@ async def create_feed(feed_url=Form(), webhook_dropdown=Form()): # TODO: Show this error on the page. return {"error": "No webhook URL found."} + # This is the webhook that will be used to send the feed to Discord. reader.set_tag(clean_feed_url, "webhook", webhook_url) # type: ignore reader.get_tag(clean_feed_url, "webhook") + # This is the default message that will be sent to Discord. + reader.set_tag(clean_feed_url, "custom_message", default_custom_message) # type: ignore + reader.get_tag(clean_feed_url, "custom_message") + + # Update the full-text search index so our new feed is searchable. reader.update_search() return RedirectResponse(url=f"/feed/?feed_url={feed_url}", status_code=303) @@ -318,12 +325,10 @@ async def set_custom(custom_message=Form(""), feed_url=Form()): Returns: Redirect to the feed. """ - - # Add the custom_message to the feed. - if custom_message: - reader.set_tag(feed_url, "custom_message", custom_message) + if custom_message := custom_message.strip(): + reader.set_tag(feed_url, "custom_message", custom_message) # type: ignore else: - reader.delete_tag(feed_url, "custom_message", missing_ok=True) + reader.set_tag(feed_url, "custom_message", settings.default_custom_message) # type: ignore # Clean URL is used to redirect to the feed page. clean_url: str = urllib.parse.quote(feed_url) @@ -495,7 +500,7 @@ async def remove_feed(feed_url=Form()): @app.get("/search", response_class=HTMLResponse) -async def search(request: Request, query): +async def search(request: Request, query: str): """ Get entries matching a full-text search query. @@ -526,6 +531,24 @@ def startup() -> None: """This is called when the server starts. It reads the settings file and starts the scheduler.""" + # Add default feed message if it doesn't exist. + # This was added in version 0.2.0. + for feed in reader.get_feeds(): + try: + reader.get_tag(feed, "custom_message") + except TagNotFoundError: + reader.set_tag(feed.url, "custom_message", default_custom_message) # type: ignore + reader.set_tag(feed.url, "has_custom_message", True) # type: ignore + + # Add has_custom_message tag if it doesn't exist. + try: + reader.get_tag(feed, "has_custom_message") + except TagNotFoundError: + if reader.get_tag(feed, "custom_message") == default_custom_message: + reader.set_tag(feed.url, "has_custom_message", False) # type: ignore + else: + reader.set_tag(feed.url, "has_custom_message", True) # type: ignore + scheduler: BackgroundScheduler = BackgroundScheduler() # Update all feeds every 15 minutes. diff --git a/discord_rss_bot/settings.py b/discord_rss_bot/settings.py index 2fc6351..501265d 100644 --- a/discord_rss_bot/settings.py +++ b/discord_rss_bot/settings.py @@ -9,6 +9,8 @@ logging.basicConfig(level=logging.INFO, format=logging_format) data_dir: str = user_data_dir(appname="discord_rss_bot", appauthor="TheLovinator", roaming=True) os.makedirs(data_dir, exist_ok=True) +default_custom_message: str = "{{entry_title}}\n{{entry_link}}" + def get_webhook_for_entry(custom_reader: Reader, entry: Entry) -> str: """ diff --git a/discord_rss_bot/templates/custom.html b/discord_rss_bot/templates/custom.html index b8c2c2e..6d32ace 100644 --- a/discord_rss_bot/templates/custom.html +++ b/discord_rss_bot/templates/custom.html @@ -202,7 +202,7 @@ <li> <code> {% raw %} - Hello {{ entry_author }}\n{{ feed_title }}\n{{ entry_read }} + Hello {{ entry_author }}\n{{ feed_title }}\n{{ entry_read -}} {% endraw %} </code> </li> @@ -213,7 +213,7 @@ <pre> Hello {{ entry.author }} {{ feed.title }} -{{ entry.read }} +{{ entry.read -}} </pre> </code> </li> @@ -227,7 +227,8 @@ Hello {{ entry.author }} type="text" class="form-control bg-dark border-dark text-muted" id="custom_message" - value="{% if custom_message %} {{ custom_message }}{% endif %}"/> + value="{% if custom_message -%} + {{ custom_message }}{%- endif %}"/> </div> </div> <!-- Add a hidden feed_url field to the form -->