diff --git a/discord_rss_bot/feeds.py b/discord_rss_bot/feeds.py index 2bfacd7..145d6fb 100644 --- a/discord_rss_bot/feeds.py +++ b/discord_rss_bot/feeds.py @@ -24,7 +24,7 @@ Exceptions: from typing import Iterable from discord_webhook import DiscordWebhook -from reader import Entry, Reader +from reader import Entry, Reader, TagNotFoundError from requests import Response from discord_rss_bot.settings import get_reader @@ -57,17 +57,79 @@ def send_to_discord(custom_reader: Reader | None = None, feed=None, do_once=Fals for entry in entries: # Set the webhook to read, so we don't send it again. - reader.set_entry_read(entry, True) + reader.set_entry_read(entry, True) # type: ignore # Get the webhook from the feed. - webhook_url: str = str(reader.get_tag(entry.feed_url, "webhook")) + try: + webhook_url: str = str(reader.get_tag(entry.feed_url, "webhook")) + except TagNotFoundError: + print(f"Webhook not found for feed {entry.feed_url}") + continue + webhook_message: str = f":robot: :mega: {entry.title}\n{entry.link}" webhook: DiscordWebhook = DiscordWebhook(url=webhook_url, content=webhook_message, rate_limit_retry=True) - # Send the webhook. - response: Response = webhook.execute() - if not response.ok: - reader.set_entry_read(entry, False) + try: + whitelist_title = reader.get_tag(feed, "whitelist_title") + except TagNotFoundError: + whitelist_title = "" + try: + whitelist_summary = reader.get_tag(feed, "whitelist_summary") + except TagNotFoundError: + whitelist_summary = "" + try: + whitelist_content = reader.get_tag(feed, "whitelist_content") + except TagNotFoundError: + whitelist_content = "" + + try: + blacklist_title = reader.get_tag(feed, "blacklist_title") + except TagNotFoundError: + blacklist_title = "" + try: + blacklist_summary = reader.get_tag(feed, "blacklist_summary") + except TagNotFoundError: + blacklist_summary = "" + try: + blacklist_content = reader.get_tag(feed, "blacklist_content") + except TagNotFoundError: + blacklist_content = "" + + # Check if the entry should be sent. If on the blacklist, mark as read and continue. + if whitelist_title: + if whitelist_title.lower() in entry.title.lower(): + print(f"Whitelisted because of title: {entry.title}") + response: Response = webhook.execute() + + if not response.ok: + print(f"Error: {response.status_code} {response.reason}") + reader.set_entry_read(entry, False) # type: ignore + if whitelist_summary: + if whitelist_summary.lower() in entry.summary.lower(): + print(f"Whitelisted because of summary: {entry.title}") + response: Response = webhook.execute() + + if not response.ok: + print(f"Error: {response.status_code} {response.reason}") + reader.set_entry_read(entry, False) # type: ignore + # if whitelist_content.lower() in entry.content.lower(): + + if blacklist_title: + if blacklist_title.lower() in entry.title.lower(): + print(f"Blacklisted because of title: {entry.title}") + reader.set_entry_read(entry, True) # type: ignore + if blacklist_summary: + if blacklist_summary.lower() in entry.summary.lower(): + print(f"Blacklisted because of summary: {entry.title}") + reader.set_entry_read(entry, True) # type: ignore + # if blacklist_content.lower() in entry.content.lower(): + + else: + response: Response = webhook.execute() + + if not response.ok: + print(f"Error: {response.status_code} {response.reason}") + reader.set_entry_read(entry, False) # type: ignore # If we only want to send one entry, we will break the loop. This is used when testing this function. if do_once: diff --git a/discord_rss_bot/main.py b/discord_rss_bot/main.py index de211fe..b5f800a 100644 --- a/discord_rss_bot/main.py +++ b/discord_rss_bot/main.py @@ -27,6 +27,8 @@ Functions: Runs on startup. """ import urllib.parse +from datetime import datetime +from enum import Enum from typing import Any, Iterable import uvicorn @@ -195,24 +197,90 @@ async def create_feed(feed_url: str = Form(), webhook_dropdown: str = Form()) -> @app.post("/pause") async def pause_feed(feed_url: str = Form()) -> dict[str, str] | RedirectResponse: - clean_url: str = urllib.parse.quote(feed_url) - # Disable/pause the feed. reader.disable_feed_updates(feed_url) + # Clean URL is used to redirect to the feed page. + clean_url: str = urllib.parse.quote(feed_url) + return RedirectResponse(url=f"/feed/?feed_url={clean_url}", status_code=303) @app.post("/unpause") async def unpause_feed(feed_url: str = Form()) -> dict[str, str] | RedirectResponse: - clean_url: str = urllib.parse.quote(feed_url) - # Enable/unpause the feed. reader.enable_feed_updates(feed_url) + # Clean URL is used to redirect to the feed page. + clean_url: str = urllib.parse.quote(feed_url) + return RedirectResponse(url=f"/feed/?feed_url={clean_url}", status_code=303) +@app.post("/whitelist") +async def set_whitelist(whitelist_title: str, whitelist_summary: str, whitelist_content: str, feed_url: str = Form()): + # Add the whitelist to the feed. + + if whitelist_title: + reader.set_tag(feed_url, "whitelist_title", whitelist) # type: ignore + if whitelist_summary: + reader.set_tag(feed_url, "whitelist_summary", whitelist) # type: ignore + if whitelist_content: + reader.set_tag(feed_url, "whitelist_content", whitelist) # type: ignore + + # Clean URL is used to redirect to the feed page. + clean_url: str = urllib.parse.quote(feed_url) + + return RedirectResponse(url=f"/feed/?feed_url={clean_url}", status_code=303) + + +@app.get("/whitelist", response_class=HTMLResponse) +async def get_whitelist(feed_url: str, request: Request) -> _TemplateResponse: + # Make feed_url a valid URL. + url: str = urllib.parse.unquote(feed_url) + + feed: Feed = reader.get_feed(url) + try: + whitelist = reader.get_tag(url, "whitelist") + except TagNotFoundError: + whitelist = "" + + context = {"request": request, "feed": feed, "whitelist": whitelist} + return templates.TemplateResponse("whitelist.html", context) + + +@app.post("/blacklist") +async def set_blacklist(blacklist_title: str, blacklist_summary: str, blacklist_content: str, feed_url: str = Form()): + # Add the blacklist to the feed. + + if blacklist_title: + reader.set_tag(feed_url, "blacklist_title", blacklist) # type: ignore + if blacklist_summary: + reader.set_tag(feed_url, "blacklist_summary", blacklist) # type: ignore + if blacklist_content: + reader.set_tag(feed_url, "blacklist_content", blacklist) # type: ignore + + # Clean URL is used to redirect to the feed page. + clean_url: str = urllib.parse.quote(feed_url) + + return RedirectResponse(url=f"/feed/?feed_url={clean_url}", status_code=303) + + +@app.get("/blacklist", response_class=HTMLResponse) +async def get_blacklist(feed_url: str, request: Request) -> _TemplateResponse: + # Make feed_url a valid URL. + url: str = urllib.parse.unquote(feed_url) + + feed: Feed = reader.get_feed(url) + try: + blacklist = reader.get_tag(url, "blacklist") + except TagNotFoundError: + blacklist = "" + + context = {"request": request, "feed": feed, "blacklist": blacklist} + return templates.TemplateResponse("blacklist.html", context) + + @app.get("/add", response_class=HTMLResponse) def get_add(request: Request) -> _TemplateResponse: """ diff --git a/discord_rss_bot/templates/blacklist.html b/discord_rss_bot/templates/blacklist.html new file mode 100644 index 0000000..0db4b3d --- /dev/null +++ b/discord_rss_bot/templates/blacklist.html @@ -0,0 +1,35 @@ +{% extends "base.html" %} +{% block title %} | Blacklist{% endblock %} +{% block content %} +
+
+ +
+ +
+
Comma separated list of words to blacklist. If a word is found in the + corresponding blacklists, the feed will not be sent. Whitelist always takes precedence over + blacklist. Leave empty to disable. Words are case-insensitive. +
+ + + + + + + + + +
+
+ + +
+ +
+
+
+{% endblock %} \ No newline at end of file diff --git a/discord_rss_bot/templates/feed.html b/discord_rss_bot/templates/feed.html index 386a6bb..5a8e7b0 100644 --- a/discord_rss_bot/templates/feed.html +++ b/discord_rss_bot/templates/feed.html @@ -24,6 +24,8 @@ {% endif %} + Whitelist + Blacklist {% for entry in entries %} diff --git a/discord_rss_bot/templates/whitelist.html b/discord_rss_bot/templates/whitelist.html new file mode 100644 index 0000000..dd09309 --- /dev/null +++ b/discord_rss_bot/templates/whitelist.html @@ -0,0 +1,35 @@ +{% extends "base.html" %} +{% block title %} | Blacklist{% endblock %} +{% block content %} +
+
+ +
+ +
+
Comma separated list of words to whitelist. Only send message to + Discord if one of these words are present in the corresponding fields. + Whitelist always takes precedence over blacklist. Leave empty to disable. + Words are case-insensitive. +
+ + + + + + + + +
+
+ + +
+ +
+
+
+{% endblock %} \ No newline at end of file