fix(images): add proxy fallback to direct source url rendering
This commit is contained in:
parent
910ca72c81
commit
fb3465fb10
4 changed files with 26 additions and 8 deletions
|
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import re
|
import re
|
||||||
|
from urllib.parse import urlparse
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
from urllib.request import Request as UrlRequest, urlopen
|
from urllib.request import Request as UrlRequest, urlopen
|
||||||
|
|
||||||
|
|
@ -124,6 +125,14 @@ def _is_probably_irrelevant_image(url: str) -> bool:
|
||||||
return any(re.search(pattern, lowered) for pattern in patterns)
|
return any(re.search(pattern, lowered) for pattern in patterns)
|
||||||
|
|
||||||
|
|
||||||
|
def _is_http_image_url(url: str) -> bool:
|
||||||
|
try:
|
||||||
|
parsed = urlparse(url)
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
return parsed.scheme in {"http", "https"} and bool(parsed.netloc)
|
||||||
|
|
||||||
|
|
||||||
def _build_image_entries(article: dict, extraction: dict, meta: dict) -> list[dict[str, object]]:
|
def _build_image_entries(article: dict, extraction: dict, meta: dict) -> list[dict[str, object]]:
|
||||||
all_images = _read_article_images(article, extraction)
|
all_images = _read_article_images(article, extraction)
|
||||||
image_review = meta.get("image_review") if isinstance(meta.get("image_review"), dict) else {}
|
image_review = meta.get("image_review") if isinstance(meta.get("image_review"), dict) else {}
|
||||||
|
|
@ -371,15 +380,19 @@ def admin_article_image_decision(
|
||||||
|
|
||||||
@router.get("/admin/images/proxy")
|
@router.get("/admin/images/proxy")
|
||||||
def admin_image_proxy(request: Request, url: str):
|
def admin_image_proxy(request: Request, url: str):
|
||||||
user = _admin_user(request)
|
if not _is_http_image_url(url):
|
||||||
if not user:
|
|
||||||
return Response(status_code=401)
|
|
||||||
|
|
||||||
if not (url.startswith("http://") or url.startswith("https://")):
|
|
||||||
return Response(status_code=400)
|
return Response(status_code=400)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
req = UrlRequest(url=url, headers={"User-Agent": IMAGE_PROXY_USER_AGENT, "Referer": url})
|
referer = request.headers.get("referer", "")
|
||||||
|
req = UrlRequest(
|
||||||
|
url=url,
|
||||||
|
headers={
|
||||||
|
"User-Agent": IMAGE_PROXY_USER_AGENT,
|
||||||
|
"Accept": "image/avif,image/webp,image/apng,image/*,*/*;q=0.8",
|
||||||
|
"Referer": referer or url,
|
||||||
|
},
|
||||||
|
)
|
||||||
with urlopen(req, timeout=10) as resp:
|
with urlopen(req, timeout=10) as resp:
|
||||||
body = resp.read()
|
body = resp.read()
|
||||||
content_type = resp.headers.get("Content-Type", "application/octet-stream")
|
content_type = resp.headers.get("Content-Type", "application/octet-stream")
|
||||||
|
|
|
||||||
|
|
@ -210,6 +210,11 @@ button.secondary {
|
||||||
background: #f8fafc;
|
background: #f8fafc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.img-failed {
|
||||||
|
opacity: 0.3;
|
||||||
|
filter: grayscale(1);
|
||||||
|
}
|
||||||
|
|
||||||
.image-meta {
|
.image-meta {
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@
|
||||||
{% for image in article.image_entries %}
|
{% for image in article.image_entries %}
|
||||||
<article class="image-card {{ 'image-selected' if image.is_selected else '' }} {{ 'image-excluded' if image.is_excluded else '' }}">
|
<article class="image-card {{ 'image-selected' if image.is_selected else '' }} {{ 'image-excluded' if image.is_excluded else '' }}">
|
||||||
<a href="{{ image.url }}" target="_blank" rel="noopener">
|
<a href="{{ image.url }}" target="_blank" rel="noopener">
|
||||||
<img src="{{ image.proxy_url }}" alt="Artikelbild" loading="lazy" />
|
<img src="{{ image.proxy_url }}" data-fallback-src="{{ image.url }}" alt="Artikelbild" loading="lazy" onerror="if(!this.dataset.fallbackUsed){this.dataset.fallbackUsed='1';this.src=this.dataset.fallbackSrc;}else{this.classList.add('img-failed');}" />
|
||||||
</a>
|
</a>
|
||||||
<div class="image-meta">
|
<div class="image-meta">
|
||||||
{% if image.is_selected %}<span class="badge ok">Ausgewählt</span>{% endif %}
|
{% if image.is_selected %}<span class="badge ok">Ausgewählt</span>{% endif %}
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@
|
||||||
<div class="subtle">Legal: {{ "OK" if a.legal_checked else "offen" }}</div>
|
<div class="subtle">Legal: {{ "OK" if a.legal_checked else "offen" }}</div>
|
||||||
{% if a.selected_image_url %}
|
{% if a.selected_image_url %}
|
||||||
<div class="subtle">Hauptbild gesetzt</div>
|
<div class="subtle">Hauptbild gesetzt</div>
|
||||||
<a href="{{ a.selected_image_url }}" target="_blank" rel="noopener"><img src="{{ a.selected_image_proxy_url }}" alt="Hauptbild" class="thumb" loading="lazy" /></a>
|
<a href="{{ a.selected_image_url }}" target="_blank" rel="noopener"><img src="{{ a.selected_image_proxy_url }}" data-fallback-src="{{ a.selected_image_url }}" alt="Hauptbild" class="thumb" loading="lazy" onerror="if(!this.dataset.fallbackUsed){this.dataset.fallbackUsed='1';this.src=this.dataset.fallbackSrc;}else{this.classList.add('img-failed');}" /></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if a.summary %}
|
{% if a.summary %}
|
||||||
<div><strong>Summary:</strong> {{ a.summary }}</div>
|
<div><strong>Summary:</strong> {{ a.summary }}</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue