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 ![alt text](image url).
+    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 -->