Made the feed config page less shit

This commit is contained in:
Joakim Hellsén 2026-07-18 06:25:29 +02:00
commit 59d9062ded
Signed by: Joakim Hellsén
SSH key fingerprint: SHA256:/9h/CsExpFp+PRhsfA0xznFx2CGfTT5R/kpuFfUgEQk

View file

@ -103,7 +103,7 @@
{% elif delivery_mode == "screenshot" %} {% elif delivery_mode == "screenshot" %}
<li>Screenshot layout: {{ screenshot_layout }}.</li> <li>Screenshot layout: {{ screenshot_layout }}.</li>
{% endif %} {% endif %}
<li>Webhook text is truncated to {{ webhook_text_length_limit }} characters.</li> <li>Webhook text</li> is truncated to {{ webhook_text_length_limit }} characters.</li>
<li> <li>
Filters: Filters:
{% if has_blacklist_filters and has_whitelist_filters %} {% if has_blacklist_filters and has_whitelist_filters %}
@ -161,86 +161,93 @@
<button class="btn btn-danger btn-sm" name="feed_url" value="{{ feed.url }}">Pause</button> <button class="btn btn-danger btn-sm" name="feed_url" value="{{ feed.url }}">Pause</button>
</form> </form>
{% endif %} {% endif %}
</div>
</section>
<div class="row row-cols-1 row-cols-lg-2 g-3 mt-2">
<div class="col">
<div class="card border border-secondary shadow-sm h-100 rounded-0">
<div class="card-header bg-transparent border-secondary text-muted text-uppercase small fw-semibold">
Delivery Settings
</div>
<div class="card-body">
<section class="mb-3">
<h4 class="h6 text-muted mb-2">Delivery Mode</h4>
<p class="text-muted small mb-2">
Choose between:<br>
Embed: a Discord embed with title, description, and images.<br>
{% if not "youtube.com/feeds/videos.xml" in feed.url %} {% if not "youtube.com/feeds/videos.xml" in feed.url %}
{% if delivery_mode == "embed" %} Screenshot: full-page screenshot of the entry link.<br>
<form action="/use_text" method="post" class="d-inline"> {% endif %}
<button class="btn btn-outline-light btn-sm" Text: plain message.
name="feed_url" </p>
value="{{ feed.url }}">Send text message instead of embed</button> <div class="d-flex" role="group" aria-label="Delivery mode">
</form> {% if delivery_mode != "embed" %}
{% elif delivery_mode == "screenshot" %}
<form action="/use_text" method="post" class="d-inline">
<button class="btn btn-outline-light btn-sm"
name="feed_url"
value="{{ feed.url }}">Send text message instead of screenshot</button>
</form>
{% else %}
<form action="/use_embed" method="post" class="d-inline"> <form action="/use_embed" method="post" class="d-inline">
<button class="btn btn-outline-light btn-sm" <button class="btn btn-outline-light btn-sm"
style="border-top-right-radius: 0; border-bottom-right-radius: 0;"
name="feed_url" name="feed_url"
value="{{ feed.url }}">Send embed instead of text message</button> value="{{ feed.url }}">Embed</button>
</form> </form>
{% else %}
<span class="btn btn-primary btn-sm disabled"
style="border-top-right-radius: 0; border-bottom-right-radius: 0;">Embed</span>
{% endif %} {% endif %}
{% if not "youtube.com/feeds/videos.xml" in feed.url %}
{% if delivery_mode != "screenshot" %}
<form action="/use_screenshot" method="post" class="d-inline">
<button class="btn btn-outline-light btn-sm rounded-0"
name="feed_url"
value="{{ feed.url }}">Screenshot</button>
</form>
{% else %}
<span class="btn btn-primary btn-sm disabled rounded-0">Screenshot</span>
{% endif %}
{% endif %}
{% if delivery_mode != "text" %}
<form action="/use_text" method="post" class="d-inline">
<button class="btn btn-outline-light btn-sm"
style="border-top-left-radius: 0; border-bottom-left-radius: 0;"
name="feed_url"
value="{{ feed.url }}">Text</button>
</form>
{% else %}
<span class="btn btn-primary btn-sm disabled"
style="border-top-left-radius: 0; border-bottom-left-radius: 0;">Text</span>
{% endif %} {% endif %}
</div> </div>
</section> </section>
{% if not "youtube.com/feeds/videos.xml" in feed.url %} {% if delivery_mode == "screenshot" and not "youtube.com/feeds/videos.xml" in feed.url %}
<section class="mt-4 pt-3 border-top border-secondary-subtle"> <hr class="border-secondary" />
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2 mb-2"> <section class="mb-3">
<h3 class="h6 text-uppercase text-muted mb-0">Screenshot Delivery</h3> <h4 class="h6 text-muted mb-2">Screenshot Layout</h4>
<span class="badge {{ 'bg-info' if delivery_mode == 'screenshot' else 'bg-secondary' }}">
{% if delivery_mode == "screenshot" %}
Active:
{% if screenshot_layout == "mobile" %}
Mobile
{% else %}
Desktop
{% endif %}
{% else %}
Inactive
{% endif %}
</span>
</div>
<p class="text-muted mb-3">
Screenshot delivery sends a full-page screenshot of the entry link instead of the normal
embed or text message.
</p>
<div class="d-flex flex-wrap gap-2"> <div class="d-flex flex-wrap gap-2">
{% if delivery_mode != "screenshot" %}
<form action="/use_screenshot" method="post" class="d-inline">
<button class="btn btn-outline-light btn-sm"
name="feed_url"
value="{{ feed.url }}">Use screenshot delivery</button>
</form>
{% else %}
<form action="/use_embed" method="post" class="d-inline">
<button class="btn btn-outline-light btn-sm"
name="feed_url"
value="{{ feed.url }}">Disable screenshot delivery</button>
</form>
{% if screenshot_layout == "mobile" %} {% if screenshot_layout == "mobile" %}
<span class="btn btn-primary btn-sm disabled">Mobile</span>
<form action="/use_screenshot_desktop" method="post" class="d-inline"> <form action="/use_screenshot_desktop" method="post" class="d-inline">
<button class="btn btn-outline-light btn-sm" <button class="btn btn-outline-light btn-sm"
name="feed_url" name="feed_url"
value="{{ feed.url }}">Use desktop screenshot layout</button> value="{{ feed.url }}">Desktop</button>
</form> </form>
{% else %} {% else %}
<form action="/use_screenshot_mobile" method="post" class="d-inline"> <form action="/use_screenshot_mobile" method="post" class="d-inline">
<button class="btn btn-outline-secondary btn-sm" <button class="btn btn-outline-light btn-sm"
name="feed_url" name="feed_url"
value="{{ feed.url }}">Use mobile screenshot layout</button> value="{{ feed.url }}">Mobile</button>
</form> </form>
{% endif %} <span class="btn btn-primary btn-sm disabled">Desktop</span>
{% endif %} {% endif %}
</div> </div>
<div class="mt-2 screenshot-requirement"> <div class="mt-2 small text-muted">
Screenshot mode requires Chromium to be installed for Playwright. Run Requires Chromium for Playwright. Run
<code>uv run playwright install chromium</code> once on this machine. <code class="text-light">uv run playwright install chromium</code> once.
</div> </div>
</section> </section>
<section class="mt-4 pt-3 border-top border-secondary-subtle"> {% endif %}
{% if not "youtube.com/feeds/videos.xml" in feed.url %}
<hr class="border-secondary" />
<section class="mb-3">
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2 mb-2"> <div class="d-flex flex-wrap align-items-center justify-content-between gap-2 mb-2">
<h3 class="h6 text-uppercase text-muted mb-0">Image Delivery</h3> <h4 class="h6 text-muted mb-0">Image Delivery</h4>
<span class="badge {{ 'bg-info' if media_gallery_image_limit < max_media_gallery_items else 'bg-secondary' }}"> <span class="badge {{ 'bg-info' if media_gallery_image_limit < max_media_gallery_items else 'bg-secondary' }}">
{% if media_gallery_image_limit == 0 %} {% if media_gallery_image_limit == 0 %}
No images No images
@ -251,10 +258,8 @@
{% endif %} {% endif %}
</span> </span>
</div> </div>
<p id="imageDeliveryHelp" class="text-muted mb-3"> <p id="imageDeliveryHelp" class="text-muted small mb-2">
Choose 0 to send no entry images, 1 for the first image only, How many images to include per entry. Only applies to embed mode.
or up to {{ max_media_gallery_items }} for a Discord media gallery.
This only affects embed delivery.
</p> </p>
<form action="/set_feed_media_gallery_image_limit" <form action="/set_feed_media_gallery_image_limit"
method="post" method="post"
@ -278,7 +283,7 @@
oninput="this.form.elements.image_limit_value.value = this.value" /> oninput="this.form.elements.image_limit_value.value = this.value" />
<div class="d-flex justify-content-between text-muted small"> <div class="d-flex justify-content-between text-muted small">
<span>0</span> <span>0</span>
<span>{{ max_media_gallery_items }}</span> </span> <span>{{ max_media_gallery_items }}</span>
</div> </div>
</div> </div>
<button class="btn btn-outline-light btn-sm" type="submit">Save image limit</button> <button class="btn btn-outline-light btn-sm" type="submit">Save image limit</button>
@ -286,14 +291,15 @@
</form> </form>
</section> </section>
{% endif %} {% endif %}
<section class="mt-4 pt-3 border-top border-secondary-subtle"> <hr class="border-secondary" />
<section>
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2 mb-2"> <div class="d-flex flex-wrap align-items-center justify-content-between gap-2 mb-2">
<h3 class="h6 text-uppercase text-muted mb-0">Text Delivery</h3> <h4 class="h6 text-muted mb-0">Text Delivery</h4>
<span class="badge {{ 'bg-info' if webhook_text_length_limit < max_webhook_text_length_limit else 'bg-secondary' }}"> <span class="badge {{ 'bg-info' if webhook_text_length_limit < max_webhook_text_length_limit else 'bg-secondary' }}">
Max {{ webhook_text_length_limit }} characters Max {{ webhook_text_length_limit }} characters
</span> </span>
</div> </div>
<p id="textDeliveryHelp" class="text-muted mb-3"> <p id="textDeliveryHelp" class="text-muted small mb-2">
Limit message length. Text mode allows values up to 4000 characters. Embeds are capped at 2000 characters. Limit message length. Text mode allows values up to 4000 characters. Embeds are capped at 2000 characters.
</p> </p>
<form action="/set_feed_webhook_text_length_limit" <form action="/set_feed_webhook_text_length_limit"
@ -318,35 +324,20 @@
</div> </div>
</form> </form>
</section> </section>
<section class="mt-4 pt-3 border-top border-secondary-subtle">
<h3 class="h6 text-uppercase text-muted mb-3">Customization</h3>
<div class="d-flex flex-wrap gap-2">
<a class="btn btn-sm btn-outline-light"
href="/whitelist?feed_url={{ feed.url|encode_url }}">Whitelist</a>
<a class="btn btn-sm btn-outline-light"
href="/blacklist?feed_url={{ feed.url|encode_url }}">Blacklist</a>
<a class="btn btn-sm btn-outline-light"
href="/custom?feed_url={{ feed.url|encode_url }}">
Customize message
{% if delivery_mode == "text" %}(Currently active){% endif %}
</a>
{% if not "youtube.com/feeds/videos.xml" in feed.url %}
<a class="btn btn-sm btn-outline-light"
href="/embed?feed_url={{ feed.url|encode_url }}">
Customize embed
{% if delivery_mode == "embed" %}(Currently active){% endif %}
</a>
{% endif %}
</div> </div>
{% if is_steam_feed %} </div>
<div class="form-text mt-2">Steam feeds can enable thumbnails in embed settings.</div> </div>
{% endif %} <div class="col">
</section> <div class="card border border-secondary shadow-sm h-100 rounded-0">
<section class="mt-4 pt-3 border-top border-secondary-subtle"> <div class="card-header bg-transparent border-secondary text-muted text-uppercase small fw-semibold">
<h3 class="h6 text-uppercase text-muted mb-3">Feed URL</h3> Feed Configuration
</div>
<div class="card-body">
<section class="mb-3">
<h4 class="h6 text-muted mb-2">Feed URL</h4>
<form action="/change_feed_url" method="post" class="mb-0"> <form action="/change_feed_url" method="post" class="mb-0">
<input type="hidden" name="old_feed_url" value="{{ feed.url }}" /> <input type="hidden" name="old_feed_url" value="{{ feed.url }}" />
<div class="input-group input-group-sm feed-page__content"> <div class="input-group input-group-sm">
<input type="url" <input type="url"
class="form-control feed-page__wrap" class="form-control feed-page__wrap"
name="new_feed_url" name="new_feed_url"
@ -356,22 +347,23 @@
</div> </div>
</form> </form>
</section> </section>
<section class="mt-4 pt-3 border-top border-secondary-subtle"> <hr class="border-secondary" />
<h3 class="h6 text-uppercase text-muted mb-3">Webhook</h3> <section class="mb-3">
<h4 class="h6 text-muted mb-2">Webhook</h4>
{% if current_webhook_name %} {% if current_webhook_name %}
<p class="text-muted mb-3"> <p class="text-muted small mb-2">
Current webhook: Current webhook:
<strong>{{ current_webhook_name }}</strong> <strong>{{ current_webhook_name }}</strong>
</p> </p>
{% elif current_webhook_url %} {% elif current_webhook_url %}
<p class="text-warning mb-3">This feed references a missing webhook. Choose a webhook below to reattach it.</p> <p class="text-warning small mb-2">This feed references a missing webhook. Choose a webhook below to reattach it.</p>
{% else %} {% else %}
<p class="text-warning mb-3">No webhook is attached to this feed yet.</p> <p class="text-warning small mb-2">No webhook is attached to this feed yet.</p>
{% endif %} {% endif %}
{% if webhooks %} {% if webhooks %}
<form action="/attach_feed_webhook" <form action="/attach_feed_webhook"
method="post" method="post"
class="d-flex flex-wrap align-items-center gap-2 mb-0"> class="d-flex flex-wrap align-items-center gap-2 mb-2">
<input type="hidden" name="feed_url" value="{{ feed.url }}" /> <input type="hidden" name="feed_url" value="{{ feed.url }}" />
<input type="hidden" <input type="hidden"
name="redirect_to" name="redirect_to"
@ -394,9 +386,9 @@
<button class="btn btn-outline-light btn-sm" type="submit">Save webhook</button> <button class="btn btn-outline-light btn-sm" type="submit">Save webhook</button>
</form> </form>
{% else %} {% else %}
<p class="text-muted mb-0">Add a webhook first to attach this feed.</p> <p class="text-muted small mb-2">Add a webhook first to attach this feed.</p>
{% endif %} {% endif %}
<div class="mt-3 d-flex flex-wrap align-items-center gap-2"> <div class="d-flex flex-wrap align-items-center gap-2">
<span class="badge {{ 'bg-success' if save_sent_webhooks else 'bg-secondary' }}"> <span class="badge {{ 'bg-success' if save_sent_webhooks else 'bg-secondary' }}">
Sent webhook tracking: Sent webhook tracking:
{{ 'Enabled' if save_sent_webhooks else 'Disabled' }} {{ 'Enabled' if save_sent_webhooks else 'Disabled' }}
@ -414,34 +406,10 @@
href="/sent_webhooks?feed_url={{ feed.url|encode_url }}">View sent webhooks</a> href="/sent_webhooks?feed_url={{ feed.url|encode_url }}">View sent webhooks</a>
</div> </div>
</section> </section>
<section class="mt-4 pt-3 border-top border-secondary-subtle"> <hr class="border-secondary" />
<h3 class="h6 text-uppercase text-muted mb-3">Feed Information</h3> <section>
<div class="row g-2 text-muted small"> <h4 class="h6 text-muted mb-2">Update Interval</h4>
<div class="col-12 col-md-6"> <div class="d-flex flex-wrap align-items-center gap-2 mb-2">
<div class="p-2">Added: {{ feed.added | relative_time }}</div>
</div>
<div class="col-12 col-md-6">
<div class="p-2">Last Updated: {{ feed.last_updated | relative_time }}</div>
</div>
<div class="col-12 col-md-6">
<div class="p-2">Last Retrieved: {{ feed.last_retrieved | relative_time }}</div>
</div>
<div class="col-12 col-md-6">
<div class="p-2">Next Update: {{ feed.update_after | relative_time }}</div>
</div>
<div class="col-12 col-md-6">
<div class="p-2">
Updates:
<span class="badge {{ 'bg-success' if feed.updates_enabled else 'bg-danger' }}">
{{ 'Enabled' if feed.updates_enabled else 'Disabled' }}
</span>
</div>
</div>
</div>
</section>
<section class="mt-4 pt-3 border-top border-secondary-subtle">
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2 mb-3">
<h3 class="h6 text-uppercase text-muted mb-0">Update Interval</h3>
<span class="badge {% if feed_interval %} bg-info {% else %} bg-secondary {% endif %}"> <span class="badge {% if feed_interval %} bg-info {% else %} bg-secondary {% endif %}">
{% if feed_interval %} {% if feed_interval %}
Custom Custom
@ -450,7 +418,7 @@
{% endif %} {% endif %}
</span> </span>
</div> </div>
<p class="text-muted mb-3"> <p class="text-muted small mb-2">
Current: Current:
<strong> <strong>
{% if feed_interval %} {% if feed_interval %}
@ -487,6 +455,73 @@
</div> </div>
</section> </section>
</div> </div>
</div>
</div>
</div>
<div class="row row-cols-1 row-cols-lg-2 g-3 mt-2">
<div class="col">
<div class="card border border-secondary shadow-sm h-100 rounded-0">
<div class="card-header bg-transparent border-secondary text-muted text-uppercase small fw-semibold">
Customization
</div>
<div class="card-body">
<div class="d-flex flex-wrap gap-2">
<a class="btn btn-sm btn-outline-light"
href="/whitelist?feed_url={{ feed.url|encode_url }}">Whitelist</a>
<a class="btn btn-sm btn-outline-light"
href="/blacklist?feed_url={{ feed.url|encode_url }}">Blacklist</a>
<div class="btn-group btn-group-sm" role="group">
<a class="btn {{ 'btn-primary' if delivery_mode == 'text' else 'btn-outline-light' }}"
href="/custom?feed_url={{ feed.url|encode_url }}">
Customize message
</a>
{% if not "youtube.com/feeds/videos.xml" in feed.url %}
<a class="btn {{ 'btn-primary' if delivery_mode == 'embed' else 'btn-outline-light' }}"
href="/embed?feed_url={{ feed.url|encode_url }}">
Customize embed
</a>
{% endif %}
</div>
</div>
{% if is_steam_feed %}
<div class="form-text small mt-2">Steam feeds can enable thumbnails in embed settings.</div>
{% endif %}
</div>
</div>
</div>
<div class="col">
<div class="card border border-secondary shadow-sm h-100 rounded-0">
<div class="card-header bg-transparent border-secondary text-muted text-uppercase small fw-semibold">
Feed Information
</div>
<div class="card-body">
<div class="row g-2 text-muted small">
<div class="col-12 col-md-6">
<div class="p-2">Added: {{ feed.added | relative_time }}</div>
</div>
<div class="col-12 col-md-6">
<div class="p-2">Last Updated: {{ feed.last_updated | relative_time }}</div>
</div>
<div class="col-12 col-md-6">
<div class="p-2">Last Retrieved: {{ feed.last_retrieved | relative_time }}</div>
</div>
<div class="col-12 col-md-6">
<div class="p-2">Next Update: {{ feed.update_after | relative_time }}</div>
</div>
<div class="col-12 col-md-6">
<div class="p-2">
Updates:
<span class="badge {{ 'bg-success' if feed.updates_enabled else 'bg-danger' }}">
{{ 'Enabled' if feed.updates_enabled else 'Disabled' }}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</article> </article>
</div> </div>
<div class="col-12"> <div class="col-12">