import os
import json
import io
import zipfile
from flask import Flask, render_template_string, request, session, redirect, url_for, send_from_directory, send_file
app = Flask(__name__)
# WICHTIG: Ändere diesen Key für den produktiven Einsatz
app.secret_key = '6a305032-9668-43c3-9a72-a407d5be988f'
# Konfiguration
PASSWORD = 'toniessindteuer'
BASE_DIR = '/mnt/NAS/Toniebox/'
# ---------------------------------------------------------
# HTML & JS Template (Frontend)
# ---------------------------------------------------------
TEMPLATE = """
Tonieflix
Abmelden
🎧 Tonieflix
{% for book in books %}
{% if book.has_cover %}
 }})
{% else %}

{% endif %}
{{ book.name }}
{% endfor %}
"""
LOGIN_TEMPLATE = """
Login - Toniboni
Toniboni Login
"""
# ---------------------------------------------------------
# Backend Logik & Routen
# ---------------------------------------------------------
@app.before_request
def require_login():
if request.endpoint not in ['login'] and not session.get('logged_in'):
return redirect(url_for('login'))
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
if request.form.get('password') == PASSWORD:
session['logged_in'] = True
return redirect(url_for('index'))
else:
return "Falsches Passwort!", 403
return render_template_string(LOGIN_TEMPLATE)
@app.route('/logout')
def logout():
session.clear()
return redirect(url_for('login'))
@app.route('/')
def index():
books = []
if os.path.exists(BASE_DIR):
for item in sorted(os.listdir(BASE_DIR)):
item_path = os.path.join(BASE_DIR, item)
if os.path.isdir(item_path):
files = os.listdir(item_path)
tracks = sorted([f for f in files if f.lower().endswith(('.mp3', '.ogg'))])
has_cover = any(f.lower() == 'cover.jpg' for f in files)
if tracks:
books.append({
'name': item,
'tracks': tracks,
'has_cover': has_cover
})
return render_template_string(TEMPLATE, books=books)
@app.route('/cover/')
def serve_cover(book_name):
book_path = os.path.join(BASE_DIR, book_name)
return send_from_directory(book_path, 'cover.jpg')
@app.route('/stream//')
def serve_audio(book_name, track_name):
book_path = os.path.join(BASE_DIR, book_name)
return send_from_directory(book_path, track_name)
@app.route('/download/')
def download_book(book_name):
book_path = os.path.join(BASE_DIR, book_name)
# Sicherheitscheck: Existiert der Ordner?
if not os.path.isdir(book_path):
return "Hörbuch nicht gefunden", 404
# ZIP-Datei im Arbeitsspeicher erstellen
memory_file = io.BytesIO()
# ZIP_STORED nutzt keine Kompression (geht extrem schnell, gut für MP3s)
with zipfile.ZipFile(memory_file, 'w', zipfile.ZIP_STORED) as zf:
for root, dirs, files in os.walk(book_path):
for file in files:
file_path = os.path.join(root, file)
# Schreibe Datei ins ZIP (nutzt Dateinamen ohne den absoluten NAS-Pfad)
zf.write(file_path, arcname=file)
memory_file.seek(0)
# Datei an den Browser schicken
return send_file(
memory_file,
download_name=f"{book_name}.zip",
as_attachment=True,
mimetype='application/zip'
)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5005)