templates/_settings_feeds_fetch_tiers.html
Rama main · réplica de lectura del repositorio original.
{# Settings → Feeds → Fetch Tiers. Served by /settings/feeds/panel/fetch-tiers
and injected on first open of that view. Shows which feeds are routing
through each outbound-fetch escalation tier (paid VPN proxy, home-IP
Tailscale, FlareSolverr) right now, so it's visible how much each is
actually being exposed rather than only discoverable one feed's
Properties at a time. Reuses the .problem-feed-* classes the Stale/Failing
lists already use. #}
{% macro tier_section(title, hint, rows) %}
<div class="fetch-tier-section">
<h4 class="fetch-tier-title">{{ title }} <span class="feeds-tab-count">{{ rows | length }}</span></h4>
<p class="muted fetch-tier-hint">{{ hint }}</p>
{% if rows %}
<ul class="problem-feed-list">
{% for row in rows %}
<li class="problem-feed-item" data-feed-url="{{ row.feed_url }}">
<div class="problem-feed-row">
<button type="button" class="problem-feed-link" data-problem-feed-properties data-feed-url="{{ row.feed_url }}" title="{{ row.feed_url }}">{{ row.feed_title }}</button>
<div class="problem-feed-actions">
<a class="problem-feed-action" href="/?folder_id={{ selected_folder_id }}&list_feed_url={{ row.feed_url | urlencode }}&read_filter=all" title="View this feed's posts in the reader"><span class="material-symbols-rounded" aria-hidden="true">list_alt</span></a>
<a class="problem-feed-action" href="{{ row.feed_url }}" target="_blank" rel="noopener noreferrer" title="Open feed URL"><span class="material-symbols-rounded" aria-hidden="true">open_in_new</span></a>
</div>
</div>
<div class="problem-feed-meta">
<span>{{ row.reason }}</span>
<span>Flagged: {{ row.flagged_at }}</span>
</div>
</li>
{% endfor %}
</ul>
{% else %}
<p class="muted">None right now.</p>
{% endif %}
</div>
{% endmacro %}
{{ tier_section("Paid VPN proxy", "Feeds escalated to the gluetun proxy after a plain fetch was refused.", proxy_rows) }}
{{ tier_section("Home IP (Tailscale)", "Feeds escalated further, past the proxy, to your home network's exit IP.", tailscale_rows) }}
{{ tier_section("FlareSolverr", "Feeds needing a real headless-Chrome challenge solve (Cloudflare/DDoS-Guard) — routed through whichever of the above is also active for the feed.", flaresolverr_rows) }}
{# Page fetches: tag/lead-image scraping and the saved-article re-fetch path
share one ladder (services/page_fetch.py) with the three feed tables above,
but its memory is per-HOST and in-memory (not persisted feed rows) — a
demand-driven single-URL fetch, not an hourly cron, so it's shown as its
own list rather than folded into the sections above. #}
<div class="fetch-tier-section">
<h4 class="fetch-tier-title">Page fetches (this session) <span class="feeds-tab-count">{{ page_fetch_rows | length }}</span></h4>
<p class="muted fetch-tier-hint">Hosts the tag/lead-image scraper and saved-article re-fetch have escalated for, since the last restart — separate from the feed tables above.</p>
{% if page_fetch_rows %}
<ul class="problem-feed-list">
{% for row in page_fetch_rows %}
<li class="problem-feed-item">
<div class="problem-feed-row">
<span class="problem-feed-link" title="{{ row.host }}">{{ row.host }}</span>
</div>
<div class="problem-feed-meta">
<span>{% if row.learned_tier %}Last worked via: {{ row.learned_tier }}{% else %}No successful fetch yet{% endif %}</span>
{% if row.blocked %}
<span>Cooling down (past {{ row.blocked_after_tier }}{% if row.challenge %}, {{ row.challenge }}{% endif %})</span>
{% endif %}
{% if row.has_cookies %}
<span title="A flaresolverr solve's cookies are cached for this host, so a plain fetch (e.g. the image proxy) can reuse them">Solve cookies cached</span>
{% endif %}
</div>
</li>
{% endfor %}
</ul>
{% else %}
<p class="muted">None right now.</p>
{% endif %}
</div>