Add button to send entry to Discord

This commit is contained in:
2023-01-21 14:16:08 +01:00
parent 10568a266f
commit bab4d1009c
4 changed files with 153 additions and 77 deletions

View File

@ -75,11 +75,13 @@ def replace_tags(feed: Feed, entry: Entry) -> str:
content = ""
if entry.summary:
summary: str = entry.summary
summary = convert_to_md(summary)
summary = remove_image_tags(message=summary)
if entry.content:
for content_item in entry.content:
content: str = content_item.value
content = convert_to_md(content)
content = remove_image_tags(message=content)
if images := get_images_from_entry(entry=entry):
@ -103,7 +105,7 @@ def replace_tags(feed: Feed, entry: Entry) -> str:
{"{{entry_added}}": entry.added},
{"{{entry_author}}": entry.author},
{"{{entry_content}}": content},
{"{{entry_content_raw}}": content},
{"{{entry_content_raw}}": entry.content[0].value if entry.content else ""},
{"{{entry_id}}": entry.id},
{"{{entry_important}}": str(entry.important)},
{"{{entry_link}}": entry.link},
@ -111,7 +113,7 @@ def replace_tags(feed: Feed, entry: Entry) -> str:
{"{{entry_read}}": str(entry.read)},
{"{{entry_read_modified}}": entry.read_modified},
{"{{entry_summary}}": summary},
{"{{entry_summary_raw}}": summary},
{"{{entry_summary_raw}}": entry.summary if entry.summary else ""},
{"{{entry_title}}": entry.title},
{"{{entry_updated}}": entry.updated},
{"{{image_1}}": first_image},
@ -121,7 +123,10 @@ def replace_tags(feed: Feed, entry: Entry) -> str:
for template, replace_with in replacement.items():
custom_message = try_to_replace(custom_message, template, replace_with)
return custom_message
# Replace \\n with newlines.
custom_message_with_newlines = custom_message.replace("\\n", "\n")
return custom_message_with_newlines
def get_custom_message(custom_reader: Reader, feed: Feed) -> str:

View File

@ -10,6 +10,53 @@ from discord_rss_bot.filter.whitelist import has_white_tags, should_be_sent
from discord_rss_bot.settings import default_custom_message, get_reader
def get_entry_from_id(entry_id: str, custom_reader: Reader | None = None) -> Entry | None:
"""
Get an entry from an ID.
Args:
entry_id: The ID of the entry.
custom_reader: If we should use a custom reader instead of the default one.
Returns:
Entry: The entry with the ID. None if it doesn't exist.
"""
# Get the default reader if we didn't get a custom one.
reader: Reader = get_reader() if custom_reader is None else custom_reader
# Get the entry from the ID, or return None if it doesn't exist.
return next((entry for entry in reader.get_entries() if entry.id == entry_id), None)
def send_entry_to_discord(entry: Entry, custom_reader: Reader | None = None):
"""
Send a single entry to Discord.
Args:
entry: The entry to send to Discord.
"""
# Get the default reader if we didn't get a custom one.
reader: Reader = get_reader() if custom_reader is None else custom_reader
# Get the webhook URL for the entry.
webhook_url: str = settings.get_webhook_for_entry(reader, entry)
if not webhook_url:
return "No webhook URL found."
# Try to get the custom message for the feed. If the user has none, we will use the default 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)
response: Response = webhook.execute()
if not response.ok:
return f"Error sending entry to Discord: {response.text}"
def send_to_discord(custom_reader: Reader | None = None, feed: Feed | None = None, do_once: bool = False) -> None:
"""
Send entries to Discord.

View File

@ -14,7 +14,7 @@ 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, get_images_from_entry, remove_image_tags
from discord_rss_bot.feeds import send_to_discord
from discord_rss_bot.feeds import get_entry_from_id, send_entry_to_discord, 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
@ -426,13 +426,14 @@ def create_html_for_feed(entries: Iterable[Entry]) -> str:
for entry in entries:
# Get first image.
first_image = ""
first_image_text = ""
if images := get_images_from_entry(entry=entry):
first_image: str = images[0][1]
first_image_text: str = images[0][0]
else:
first_image = ""
first_image_text = ""
# Get the text from the entry.
text = "<div class='text-muted'>No content available.</div>"
if entry.summary:
summary: str = convert_to_md(entry.summary)
summary = remove_image_tags(message=summary)
@ -441,32 +442,30 @@ def create_html_for_feed(entries: Iterable[Entry]) -> str:
content: str = convert_to_md(entry.content[0].value)
content = remove_image_tags(message=content)
text = f"<div class='text-muted'>{content}</div>"
else:
text = "<div class='text-muted'>No content available.</div>"
published = ""
if entry.published:
published: str = entry.published.strftime("%Y-%m-%d %H:%M:%S")
else:
published = ""
blacklisted = ""
if entry_is_blacklisted(entry):
blacklisted = "<span class='badge bg-danger'>Blacklisted</span>"
else:
blacklisted = ""
whitelisted = ""
if entry_is_whitelisted(entry):
whitelisted = "<span class='badge bg-success'>Whitelisted</span>"
else:
whitelisted = ""
entry_id: str = urllib.parse.quote(entry.id)
to_disord_html: str = f"<a class='text-muted' href='/post_entry?entry_id={entry_id}'>Send to Discord</a>"
html += f"""
<div class="p-2 mb-2 border border-dark">
{blacklisted}
{whitelisted}
<h2>
<a class="text-muted text-decoration-none" href="{entry.link}">{entry.title}</a>
</h2>
{f"By { entry.author } @" if entry.author else ""} {published}
<a class="text-muted text-decoration-none" href="{entry.link}"><h2>{entry.title}</h2></a>
{f"By { entry.author } @" if entry.author else ""} {published} - {to_disord_html}
{text}
{f"<img src='{first_image}' class='img-fluid' alt='{first_image_text}'>" if first_image else ""}
</div>
@ -591,6 +590,30 @@ async def search(request: Request, query: str):
return templates.TemplateResponse("search.html", context)
@app.get("/post_entry", response_class=HTMLResponse)
async def post_entry(entry_id: str):
"""
Send a feed to Discord.
Returns:
HTMLResponse: The HTML response.
"""
# Unquote the entry id.
unquoted_entry_id: str = urllib.parse.unquote(entry_id)
print(f"Sending entry '{unquoted_entry_id}' to Discord.")
entry: Entry | None = get_entry_from_id(entry_id=unquoted_entry_id)
if entry is None:
return {"error": f"Failed to get entry '{entry_id}' when posting to Discord."}
if result := send_entry_to_discord(entry=entry):
return result
# Redirect to the feed page.
clean_url: str = entry.feed.url.strip()
return RedirectResponse(url=f"/feed/?feed_url={clean_url}", status_code=303)
@app.on_event("startup")
def startup() -> None:
"""This is called when the server starts.

View File

@ -11,196 +11,198 @@
<div class="form-text">
<ul class="list-inline">
<li>You can modify the message that is sent to Discord.</li>
<li> You can use \n to create a new line.</li>
<li> You can remove the embed from links by adding < and > around the link. (For example <{% raw %}{{entry_link}}{% endraw %}>)</li>
<br/>
<li>
<code>
{% raw %}
{{ feed_author }}
{{feed_author}}
{% endraw %}
</code>{{ feed.author }}
</code>{{feed.author}}
</li>
<li>
<code>
{% raw %}
{{ feed_added }}
{{feed_added}}
{% endraw %}
</code>{{ feed.added }}
</code>{{feed.added}}
</li>
<li>
<code>
{% raw %}
{{ feed_last_exception }}
{{feed_last_exception}}
{% endraw %}
</code>{{ feed.last_exception }}
</code>{{feed.last_exception}}
</li>
<li>
<code>
{% raw %}
{{ feed_last_updated }}
{{feed_last_updated}}
{% endraw %}
</code>{{ feed.last_updated }}
</code>{{feed.last_updated}}
</li>
<li>
<code>
{% raw %}
{{ feed_link }}
{{feed_link}}
{% endraw %}
</code>{{ feed.link }}
</code>{{feed.link}}
</li>
<li>
<code>
{% raw %}
{{ feed_subtitle }}
{{feed_subtitle}}
{% endraw %}
</code>{{ feed.subtitle }}
</code>{{feed.subtitle}}
</li>
<li>
<code>
{% raw %}
{{ feed_title }}
{{feed_title}}
{% endraw %}
</code>{{ feed.title }}
</code>{{feed.title}}
</li>
<li>
<code>
{% raw %}
{{ feed_updated }}
{{feed_updated}}
{% endraw %}
</code>{{ feed.updated }}
</code>{{feed.updated}}
</li>
<li>
<code>
{% raw %}
{{ feed_updates_enabled }}
{{feed_updates_enabled}}
{% endraw %}
</code>{{ feed.updates_enabled }}
</code>{{feed.updates_enabled}}
</li>
<li>
<code>
{% raw %}
{{ feed_url }}
{{feed_url}}
{% endraw %}
</code>{{ feed.url }}
</code>{{feed.url}}
</li>
<li>
<code>
{% raw %}
{{ feed_user_title }}
{{feed_user_title}}
{% endraw %}
</code>{{ feed.user_title }}
</code>{{feed.user_title}}
</li>
<li>
<code>
{% raw %}
{{ feed_version }}
{{feed_version}}
{% endraw %}
</code>{{ feed.version }}
</code>{{feed.version}}
</li>
<br/>
{% if entry %}
<li>
<code>
{% raw %}
{{ entry_added }}
{{entry_added}}
{% endraw %}
</code>{{ entry.added }}
</code>{{entry.added}}
</li>
<li>
<code>
{% raw %}
{{ entry_author }}
{{entry_author}}
{% endraw %}
</code>{{ entry.author }}
</code>{{entry.author}}
</li>
<li>
<code>
{% raw %}
{{ entry_content }}
{{entry_content}}
{% endraw %}
</code>{{ entry.content[0].value|discord_markdown|remove_image_tags }}
</code>{{entry.content[0].value|discord_markdown|remove_image_tags}}
</li>
<li>
<code>
{% raw %}
{{ entry_content_raw }}
{{entry_content_raw}}
{% endraw %}
</code>{{ entry.content[0].value }}
</code>{{entry.content[0].value}}
</li>
<li>
<code>
{% raw %}
{{ entry_id }}
{{entry_id}}
{% endraw %}
</code>{{ entry.id }}
</code>{{entry.id}}
</li>
<li>
<code>
{% raw %}
{{ entry_important }}
{{entry_important}}
{% endraw %}
</code>{{ entry.important }}
</code>{{entry.important}}
</li>
<li>
<code>
{% raw %}
{{ entry_link }}
{{entry_link}}
{% endraw %}
</code>{{ entry.link }}
</code>{{entry.link}}
</li>
<li>
<code>
{% raw %}
{{ entry_published }}
{{entry_published}}
{% endraw %}
</code>{{ entry.published }}
</code>{{entry.published}}
</li>
<li>
<code>
{% raw %}
{{ entry_read }}
{{entry_read}}
{% endraw %}
</code>{{ entry.read }}
</code>{{entry.read}}
</li>
<li>
<code>
{% raw %}
{{ entry_read_modified }}
{{entry_read_modified}}
{% endraw %}
</code>{{ entry.read_modified }}
</code>{{entry.read_modified}}
</li>
<li>
<code>
{% raw %}
{{ entry_summary }}
{{entry_summary}}
{% endraw %}
</code>{{ entry.summary|discord_markdown|remove_image_tags }}
</code>{{entry.summary|discord_markdown|remove_image_tags}}
</li>
<li>
<code>
{% raw %}
{{ entry_summary_raw }}
{{entry_summary_raw}}
{% endraw %}
</code>{{ entry.summary }}
</code>{{entry.summary}}
</li>
<li>
<code>
{% raw %}
{{ entry_title }}
{{entry_title}}
{% endraw %}
</code>{{ entry.title }}
</code>{{entry.title}}
</li>
<li>
<code>
{% raw %}
{{ entry_updated }}
{{entry_updated}}
{% endraw %}
</code>{{ entry.updated }}
</code>{{entry.updated}}
</li>
<br/>
<li>
<code>
{% raw %}
{{ image_1 }}
{{image_1}}
{% endraw %}
</code>First image in the entry if it exists
</li>
@ -210,7 +212,7 @@
<li>
<code>
{% raw %}
Hello {{ entry_author }}\n{{ feed_title }}\n{{ entry_read }}
{{feed_title}}\n{{entry_content}}
{% endraw %}
</code>
</li>
@ -219,9 +221,8 @@
<li>
<code>
<pre>
Hello {{ entry.author }}
{{ feed.title }}
{{ entry.read }}
{{feed.title -}}
{{- entry.content[0].value|discord_markdown|remove_image_tags -}}
</pre>
</code>
</li>
@ -241,7 +242,7 @@ Hello {{ entry.author }}
</div>
</div>
<!-- Add a hidden feed_url field to the form -->
<input type="hidden" name="feed_url" value="{{ feed.url }}"/>
<input type="hidden" name="feed_url" value="{{feed.url}}"/>
<!-- Submit button -->
<div class="d-md-flex">
<button class="btn btn-dark btn-sm">Update message</button>