From ca9cbce0839027b3df10e0280ac9edd73399e67a Mon Sep 17 00:00:00 2001 From: jbergner Date: Sun, 21 Sep 2025 19:20:28 +0200 Subject: [PATCH] bugfixes --- cmd/dashboard/main.go | 8 +++++-- web/static/js/index.js | 48 ++++++++++++++++++++++++---------------- web/static/js/stream.js | 11 +++++++++ web/templates/index.html | 2 +- 4 files changed, 47 insertions(+), 22 deletions(-) diff --git a/cmd/dashboard/main.go b/cmd/dashboard/main.go index 0ada20f..1871475 100644 --- a/cmd/dashboard/main.go +++ b/cmd/dashboard/main.go @@ -147,12 +147,16 @@ func main() { func apiStreams(w http.ResponseWriter, r *http.Request) { ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second) defer cancel() + c := &mtx.Client{BaseURL: mtxAPI, User: os.Getenv("MTX_API_USER"), Pass: os.Getenv("MTX_API_PASS")} pl, err := c.Paths(ctx) if err != nil { - http.Error(w, err.Error(), http.StatusBadGateway) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusBadGateway) + _ = json.NewEncoder(w).Encode(map[string]any{"error": err.Error()}) return } + allowed := map[string]bool{} if streamsCSV != "" { for _, s := range strings.Split(streamsCSV, ",") { @@ -174,7 +178,7 @@ func apiStreams(w http.ResponseWriter, r *http.Request) { out.Items = append(out.Items, item{Name: p.Name, Live: p.Live(), Viewers: p.Viewers()}) } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(out) + _ = json.NewEncoder(w).Encode(out) } func pageIndex(w http.ResponseWriter, r *http.Request) { diff --git a/web/static/js/index.js b/web/static/js/index.js index c658af1..10e70b9 100644 --- a/web/static/js/index.js +++ b/web/static/js/index.js @@ -1,25 +1,35 @@ async function load(){ - const r = await fetch('/api/streams'); - const data = await r.json(); + let data; + try { + const r = await fetch('/api/streams', { cache: 'no-store' }); + if (!r.ok) throw new Error('api '+r.status); + data = await r.json(); + } catch (e) { + console.warn('streams api error:', e); + // UI freundlich degradieren + document.getElementById('list').innerHTML = + '
Keine Daten (API-Fehler)
'; + return; + } const q = (document.getElementById('filter').value||'').toLowerCase(); const list = document.getElementById('list'); list.innerHTML = ''; - data.items - .filter(it => !q || it.name.toLowerCase().includes(q)) - .forEach(it => { - const a = document.createElement('a'); - a.href = '/' + encodeURIComponent(it.name); - a.className = 'card'; - a.innerHTML = ` -
-
-
${it.name}
-
Zuschauer: ${it.viewers}
-
-
${it.live ? 'LIVE' : 'Offline'}
-
`; - list.appendChild(a); - }); + data.items.filter(it => !q || it.name.toLowerCase().includes(q)).forEach(it => { + const a = document.createElement('a'); + a.href = '/' + encodeURIComponent(it.name); + a.className = 'card'; + a.innerHTML = ` +
+
+
${it.name}
+
Zuschauer: ${it.viewers}
+
+
${it.live ? 'LIVE' : 'Offline'}
+
`; + list.appendChild(a); + }); } document.getElementById('filter').addEventListener('input', load); -load(); setInterval(load, 3000); +document.getElementById('reload').addEventListener('click', load); +load(); +setInterval(load, 3000); diff --git a/web/static/js/stream.js b/web/static/js/stream.js index 20711a3..696e8b2 100644 --- a/web/static/js/stream.js +++ b/web/static/js/stream.js @@ -11,6 +11,17 @@ } async function refresh(){ + let data; + try{ + const r = await fetch('/api/streams', { cache: 'no-store' }); + if (!r.ok) throw new Error('api '+r.status); + data = await r.json(); + }catch(e){ + console.warn('streams api error:', e); + setLive(false); + viewersEl.textContent = 'Zuschauer: –'; + return; + } const r = await fetch('/api/streams'); const d = await r.json(); const it = d.items.find(x=>x.name===name); diff --git a/web/templates/index.html b/web/templates/index.html index 0ae0bcc..67d4978 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -16,7 +16,7 @@

🎬 Streams

- Neu laden +

RTMP Ingest: rtmp://HOST/<name> · HLS: http(s)://HOST/hls/<name>