From 041b60c77112f3817020b679f62501b09a886f63 Mon Sep 17 00:00:00 2001 From: Matthias Berner Date: Tue, 7 Jul 2026 22:00:35 +0200 Subject: [PATCH] Add Stream/Download buttons to global search results --- app.py | 17 ++++++++++++++++ web/index.html | 54 +++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/app.py b/app.py index f1bc088..89e0e14 100644 --- a/app.py +++ b/app.py @@ -1153,6 +1153,23 @@ def api_download_file(did): return send_file(p, as_attachment=True, download_name=download_name) +@app.route('/api/downloads//save') +def api_download_save(did): + """Speichern: Datei senden und aus Liste entfernen""" + d = DM.get(did) + if not d or d.get('status') != 'complete': + return jsonify({'error': 'not ready'}), 404 + p = d.get('path') + if not p or not os.path.exists(p): + return jsonify({'error': 'file missing'}), 404 + # Sauberer Titel als Dateiname + safe_title = re.sub(r'[^\w\-\. ]', '_', d.get('title', 'video'))[:80] + download_name = f"{safe_title}.mp4" + # Aus Liste entfernen + DM.delete(did) + return send_file(p, as_attachment=True, download_name=download_name) + + @app.route('/api/downloads/', methods=['DELETE']) def api_download_delete(did): if DM.delete(did): diff --git a/web/index.html b/web/index.html index 9605ae8..bc1c55e 100644 --- a/web/index.html +++ b/web/index.html @@ -31,6 +31,12 @@ header button { padding: 8px 16px; background: #e94560; border: none; border-rad /* Suchergebnisse Liste */ .search-results { max-width: 700px; margin: 0 auto; } .entry-list { display: flex; flex-direction: column; gap: 6px; } +.entry-actions { display: flex; gap: 4px; margin-left: auto; } +.btn-stream-sm, .btn-download-sm { width: 28px; height: 28px; border-radius: 4px; border: none; cursor: pointer; font-size: 14px; display: flex; align-items: center; justify-content: center; } +.btn-stream-sm { background: #0f3460; color: #0f0; } +.btn-download-sm { background: #0f3460; color: #ff0; } +.btn-stream-sm:hover { background: #0f0; color: #000; } +.btn-download-sm:hover { background: #ff0; color: #000; } .entry-item { display: flex; align-items: center; gap: 12px; padding: 10px 12px; background: #16213e; border-radius: 8px; cursor: pointer; transition: background 0.15s; } .entry-item:hover { background: #1a2744; } .entry-item .entry-thumb { width: 50px; height: 70px; object-fit: cover; border-radius: 4px; background: #0f3460; flex-shrink: 0; } @@ -161,16 +167,19 @@ function renderEntries() {

Suchergebnisse (${state.entries.length})

${state.entries.map((e, i) => ` -
+
${e.thumb ? `` : '
🎬
'} - `).join('')}
`; @@ -313,6 +322,41 @@ async function openSearchResult(idx) { } } +async function openSearchStream(idx) { + // Stream in neuem Tab - bleibt auf der Suchseite + await openSearchResult(idx); +} + +async function addSearchDownload(idx) { + // Download starten + const entry = state.entries[idx]; + if (!entry) return; + + const site = entry._site; + if (!site) { + alert('Site nicht gefunden'); + return; + } + + const params = new URLSearchParams({ url: entry.url || '' }); + + try { + const data = await api(`/sites/${site.id}/hosters?${params}`); + const hosters = (data.hosters || []).filter(h => typeof h === 'object'); + + if (hosters.length > 0) { + const link = hosters[0].link || hosters[0].url; + const did = await api(`/download?url=${encodeURIComponent(link)}&title=${encodeURIComponent(entry.title)}`); + alert('Download gestartet: ' + entry.title); + showDownloads(); + } else { + alert('Keine Streams gefunden für "' + entry.title + '"'); + } + } catch(e) { + alert('Fehler beim Starten des Downloads: ' + e.message); + } +} + async function pollDownload(did, idx, title) { const btn = document.getElementById(`dlbtn${idx}`); const maxWait = 120; @@ -463,10 +507,10 @@ async function deleteDownload(id) { } function saveDownload(id, btn) { - // Download starten und Button deaktivieren + // Download starten - Backend löscht danach aus Liste btn.disabled = true; btn.style.opacity = '0.5'; - location.href = `/api/downloads/${id}/file`; + location.href = `/api/downloads/${id}/save`; } function setBC(parts) {