Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
265b48905a | ||
|
|
902ab6244e |
@@ -15,9 +15,15 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Tooling
|
||||
run: apt-get update -qq && apt-get install -y -qq --no-install-recommends python3 python3-jinja2
|
||||
run: apt-get update -qq && apt-get install -y -qq --no-install-recommends python3 python3-jinja2 python3-pyflakes
|
||||
- name: Python compiles
|
||||
run: python3 -m compileall -q .
|
||||
- name: No undefined names
|
||||
# Fanger fx et manglende "import asyncio", der ellers først viser sig som
|
||||
# en 500 i drift (sket for YouTube-modulet 2026-09-20 til 2026-10-06).
|
||||
run: |
|
||||
python3 -m pyflakes *.py > pyflakes.txt || true
|
||||
if grep -E "undefined name|unable to detect undefined names" pyflakes.txt; then exit 1; fi
|
||||
- name: Templates parse
|
||||
run: |
|
||||
python3 - <<'PY'
|
||||
|
||||
@@ -7,6 +7,7 @@ from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from starlette.middleware.sessions import SessionMiddleware
|
||||
|
||||
import asyncio
|
||||
import re
|
||||
import time
|
||||
import urllib.parse
|
||||
@@ -133,7 +134,6 @@ async def dashboard_content(request: Request):
|
||||
user = current_user(request)
|
||||
if not user:
|
||||
raise HTTPException(401)
|
||||
import asyncio
|
||||
mc_task = asyncio.create_task(svc.minecraft_servers())
|
||||
apps, error = [], None
|
||||
try:
|
||||
@@ -236,7 +236,6 @@ async def admin_ops(request: Request):
|
||||
@app.get("/ops-content", response_class=HTMLResponse)
|
||||
async def ops_content(request: Request):
|
||||
require_admin(request)
|
||||
import asyncio
|
||||
version, rp, vers = await asyncio.gather(
|
||||
svc.assets_version(), svc.rp_status(), versions.all_versions())
|
||||
return templates.TemplateResponse(request, "admin_ops_body.html", {
|
||||
@@ -473,13 +472,16 @@ async def podcast_faelles_side(request: Request, key: str):
|
||||
return templates.TemplateResponse(request, "podcast_og.html", {"request": request, "og": og}, headers=headers)
|
||||
indbygget = None
|
||||
if _INDBYGGET.search(ua):
|
||||
# Messenger på iPhone blokerer også x-safari-https://, så dér er der ingen
|
||||
# knap ud af appen: vejledning til menuen + kopiér feedet til Apple Podcasts.
|
||||
# Android-udgaven af Facebooks browser følger intent://-links.
|
||||
sti = f"{request.url.hostname}{rod}/"
|
||||
if re.search(r"iPhone|iPad|iOS", ua):
|
||||
indbygget = {"knap": "Åbn i Safari", "href": f"x-safari-https://{sti}"}
|
||||
indbygget = {"platform": "ios"}
|
||||
elif "Android" in ua:
|
||||
indbygget = {"knap": "Åbn i Chrome", "href": f"intent://{sti}#Intent;scheme=https;end"}
|
||||
indbygget = {"platform": "android", "href": f"intent://{sti}#Intent;scheme=https;end"}
|
||||
else:
|
||||
indbygget = {"knap": "", "href": ""}
|
||||
indbygget = {"platform": "andet"}
|
||||
return templates.TemplateResponse(request, "podcast.html", {
|
||||
"request": request, "user": None, "is_admin": False, "rod": rod, "delt": True, "og": og,
|
||||
"indbygget": indbygget, "udsendelser": udsendelser, "saved": ""}, headers=headers)
|
||||
|
||||
+35
-5
@@ -8,6 +8,17 @@
|
||||
<meta property="og:url" content="{{ og.url }}">
|
||||
{% if og.billede %}<meta property="og:image" content="{{ og.billede }}">{% endif %}{% endif %}{% endif %}{% endblock %}
|
||||
{% block body %}
|
||||
<style>
|
||||
/* Ingen vandret scroll på iPhone: afspiller og felter må aldrig blive bredere end
|
||||
kortet, og felter skal have mindst 16 px skrift, ellers zoomer iOS ind. */
|
||||
html, body { overflow-x: hidden; }
|
||||
.pod-side { max-width: 100%; overflow-wrap: anywhere; }
|
||||
.pod-side img, .pod-side audio, .pod-side input, .pod-side .wt-card { max-width: 100%; box-sizing: border-box; }
|
||||
.pod-side audio { display: block; width: 100%; min-width: 0; }
|
||||
.pod-side input { font-size: 16px !important; min-width: 0; }
|
||||
.pod-side .wt-btn { white-space: normal; }
|
||||
</style>
|
||||
<div class="pod-side">
|
||||
{% if saved %}<div class="wt-flash">{{ saved }}</div>{% endif %}
|
||||
{% if not udsendelser %}
|
||||
<h1>Podcast</h1>
|
||||
@@ -30,11 +41,15 @@
|
||||
<h2 style="font-size:1.05rem;margin:0 0 .5rem">Abonnér i din podcast-app</h2>
|
||||
{% if indbygget %}
|
||||
<div class="wt-flash" style="margin:.4rem 0 .9rem">
|
||||
Du har åbnet siden inde i Messenger, og den kan ikke åbne podcast-apps.
|
||||
{% if indbygget.href %}Tryk her for at åbne siden i din almindelige browser, og abonnér derfra:
|
||||
<div style="margin-top:.6rem"><a class="wt-btn wt-btn--primary" href="{{ indbygget.href }}">{{ indbygget.knap }}</a></div>
|
||||
{% else %}Åbn siden i din almindelige browser (menuen ⋯ øverst), og abonnér derfra.{% endif %}
|
||||
<div class="wt-muted" style="font-size:.85rem;margin-top:.5rem">Virker knappen ikke: tryk på ⋯ øverst og vælg "Åbn i ekstern browser". Du kan også bare lytte herunder.</div>
|
||||
<p style="margin:0 0 .5rem">Du har åbnet siden inde i Messenger, og den kan ikke åbne podcast-apps. Du kan stadig lytte herunder. Vil du abonnere:</p>
|
||||
{% if indbygget.platform == "android" %}
|
||||
<p style="margin:.4rem 0"><a class="wt-btn wt-btn--primary" href="{{ indbygget.href }}">Åbn i Chrome</a></p>
|
||||
<p style="margin:.4rem 0">Virker det ikke: tryk på ⋮ øverst til højre og vælg "Åbn i ekstern browser".</p>
|
||||
{% else %}
|
||||
<p style="margin:.4rem 0"><strong>1.</strong> Tryk på ⋯ øverst til højre og vælg "Åbn i ekstern browser" (eller "Åbn i Safari"). Så virker knapperne herunder.</p>
|
||||
<p style="margin:.6rem 0 .3rem"><strong>2.</strong> Eller kopiér adressen og tilføj den selv i Apple Podcasts: <em>Bibliotek → ⋯ øverst → Følg en serie via URL</em>.</p>
|
||||
<button class="wt-btn wt-btn--primary" type="button" data-kopier-tekst="{{ udsendelser[0].feed if udsendelser else '' }}">Kopiér adressen</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<p class="wt-muted" style="margin:.2rem 0 .8rem">{% if delt %}Tryk på din app, så kommer nye episoder af sig selv. Linket er familiens fælles, så del det kun inden for familien.{% else %}Tryk på din app. Nye episoder kommer så af sig selv. Adressen er din egen, så del den ikke; familien får hver sin.{% endif %}</p>
|
||||
@@ -82,6 +97,20 @@
|
||||
</form>
|
||||
{% endif %}
|
||||
<script>
|
||||
function kopierTekst(t, knap) {
|
||||
var ok = function () { knap.textContent = 'Kopieret'; };
|
||||
var fallback = function () {
|
||||
var ta = document.createElement('textarea'); ta.value = t; ta.setAttribute('readonly', '');
|
||||
ta.style.position = 'fixed'; ta.style.top = '0'; ta.style.opacity = '0'; ta.style.fontSize = '16px';
|
||||
document.body.appendChild(ta); ta.focus(); ta.setSelectionRange(0, t.length);
|
||||
try { document.execCommand('copy'); ok(); } catch (e) { prompt('Kopiér adressen:', t); }
|
||||
document.body.removeChild(ta);
|
||||
};
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) navigator.clipboard.writeText(t).then(ok, fallback); else fallback();
|
||||
}
|
||||
document.querySelectorAll('[data-kopier-tekst]').forEach(function (b) {
|
||||
b.addEventListener('click', function () { kopierTekst(b.dataset.kopierTekst, b); });
|
||||
});
|
||||
document.querySelectorAll('[data-kopier]').forEach(function (b) {
|
||||
b.addEventListener('click', function () {
|
||||
var i = document.getElementById(b.dataset.kopier);
|
||||
@@ -92,4 +121,5 @@ document.querySelectorAll('[data-kopier]').forEach(function (b) {
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user