You can now customize the default message
This commit is contained in:
@ -1,9 +1,32 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
from reader import Entry, Feed, Reader, TagNotFoundError
|
from reader import Entry, Feed, Reader, TagNotFoundError
|
||||||
|
|
||||||
from discord_rss_bot.custom_filters import convert_to_md
|
from discord_rss_bot.custom_filters import convert_to_md
|
||||||
from discord_rss_bot.settings import get_reader
|
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:
|
def try_to_replace(custom_message: str, template: str, replace_with: str) -> str:
|
||||||
"""Try to replace a tag in custom_message.
|
"""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
|
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.
|
"""Replace tags in custom_message.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -78,7 +101,10 @@ def replace_tags(feed: Feed, entry: Entry) -> str:
|
|||||||
for replacement in list_of_replacements:
|
for replacement in list_of_replacements:
|
||||||
for template, replace_with in replacement.items():
|
for template, replace_with in replacement.items():
|
||||||
custom_message = try_to_replace(custom_message, template, replace_with)
|
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:
|
def get_custom_message(custom_reader: Reader, feed: Feed) -> str:
|
||||||
|
@ -7,7 +7,7 @@ from requests import Response
|
|||||||
from discord_rss_bot import custom_message, settings
|
from discord_rss_bot import custom_message, settings
|
||||||
from discord_rss_bot.filter.blacklist import should_be_skipped
|
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.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:
|
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:
|
else:
|
||||||
entries = reader.get_entries(feed=feed, read=False)
|
entries = reader.get_entries(feed=feed, read=False)
|
||||||
|
|
||||||
|
# Loop through the unread entries.
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
# Set the webhook to read, so we don't send it again.
|
# Set the webhook to read, so we don't send it again.
|
||||||
reader.set_entry_read(entry, True)
|
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_url: str = settings.get_webhook_for_entry(reader, entry)
|
||||||
|
|
||||||
webhook_message: str = f"{entry.title}\n{entry.link}"
|
|
||||||
|
|
||||||
if not webhook_url:
|
if not webhook_url:
|
||||||
continue
|
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)
|
webhook: DiscordWebhook = DiscordWebhook(url=webhook_url, content=webhook_message, rate_limit_retry=True)
|
||||||
|
|
||||||
if custom_message.get_custom_message(reader, entry.feed) != "":
|
# Check if the feed has a whitelist, and if it does, check if the entry is whitelisted.
|
||||||
webhook.content = custom_message.replace_tags(entry=entry, feed=entry.feed)
|
|
||||||
|
|
||||||
if feed is not None and has_white_tags(reader, feed):
|
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):
|
if should_be_sent(reader, entry):
|
||||||
response: Response = webhook.execute()
|
response: Response = webhook.execute()
|
||||||
reader.set_entry_read(entry, True)
|
reader.set_entry_read(entry, True)
|
||||||
|
@ -11,13 +11,14 @@ from fastapi.templating import Jinja2Templates
|
|||||||
from reader import Entry, EntryCounts, EntrySearchCounts, EntrySearchResult, Feed, FeedCounts, Reader, TagNotFoundError
|
from reader import Entry, EntryCounts, EntrySearchCounts, EntrySearchResult, Feed, FeedCounts, Reader, TagNotFoundError
|
||||||
from starlette.responses import RedirectResponse
|
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_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.custom_message import get_custom_message
|
||||||
from discord_rss_bot.feeds import send_to_discord
|
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.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.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.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: FastAPI = FastAPI()
|
||||||
app.mount("/static", StaticFiles(directory="discord_rss_bot/static"), name="static")
|
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.
|
# TODO: Show this error on the page.
|
||||||
return {"error": "No webhook URL found."}
|
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.set_tag(clean_feed_url, "webhook", webhook_url) # type: ignore
|
||||||
reader.get_tag(clean_feed_url, "webhook")
|
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()
|
reader.update_search()
|
||||||
|
|
||||||
return RedirectResponse(url=f"/feed/?feed_url={feed_url}", status_code=303)
|
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:
|
Returns:
|
||||||
Redirect to the feed.
|
Redirect to the feed.
|
||||||
"""
|
"""
|
||||||
|
if custom_message := custom_message.strip():
|
||||||
# Add the custom_message to the feed.
|
reader.set_tag(feed_url, "custom_message", custom_message) # type: ignore
|
||||||
if custom_message:
|
|
||||||
reader.set_tag(feed_url, "custom_message", custom_message)
|
|
||||||
else:
|
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 is used to redirect to the feed page.
|
||||||
clean_url: str = urllib.parse.quote(feed_url)
|
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)
|
@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.
|
Get entries matching a full-text search query.
|
||||||
|
|
||||||
@ -526,6 +531,24 @@ def startup() -> None:
|
|||||||
"""This is called when the server starts.
|
"""This is called when the server starts.
|
||||||
|
|
||||||
It reads the settings file and starts the scheduler."""
|
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()
|
scheduler: BackgroundScheduler = BackgroundScheduler()
|
||||||
|
|
||||||
# Update all feeds every 15 minutes.
|
# Update all feeds every 15 minutes.
|
||||||
|
@ -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)
|
data_dir: str = user_data_dir(appname="discord_rss_bot", appauthor="TheLovinator", roaming=True)
|
||||||
os.makedirs(data_dir, exist_ok=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:
|
def get_webhook_for_entry(custom_reader: Reader, entry: Entry) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -202,7 +202,7 @@
|
|||||||
<li>
|
<li>
|
||||||
<code>
|
<code>
|
||||||
{% raw %}
|
{% raw %}
|
||||||
Hello {{ entry_author }}\n{{ feed_title }}\n{{ entry_read }}
|
Hello {{ entry_author }}\n{{ feed_title }}\n{{ entry_read -}}
|
||||||
{% endraw %}
|
{% endraw %}
|
||||||
</code>
|
</code>
|
||||||
</li>
|
</li>
|
||||||
@ -213,7 +213,7 @@
|
|||||||
<pre>
|
<pre>
|
||||||
Hello {{ entry.author }}
|
Hello {{ entry.author }}
|
||||||
{{ feed.title }}
|
{{ feed.title }}
|
||||||
{{ entry.read }}
|
{{ entry.read -}}
|
||||||
</pre>
|
</pre>
|
||||||
</code>
|
</code>
|
||||||
</li>
|
</li>
|
||||||
@ -227,7 +227,8 @@ Hello {{ entry.author }}
|
|||||||
type="text"
|
type="text"
|
||||||
class="form-control bg-dark border-dark text-muted"
|
class="form-control bg-dark border-dark text-muted"
|
||||||
id="custom_message"
|
id="custom_message"
|
||||||
value="{% if custom_message %} {{ custom_message }}{% endif %}"/>
|
value="{% if custom_message -%}
|
||||||
|
{{ custom_message }}{%- endif %}"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Add a hidden feed_url field to the form -->
|
<!-- Add a hidden feed_url field to the form -->
|
||||||
|
Reference in New Issue
Block a user