Session 2026-04-20: Medien-Konvertierung, Umami Analytics, Username/Privacy
- HEIC→JPEG, MOV/AVI→MP4 Konvertierung bei allen Upload-Endpoints (media_utils.py) - ffmpeg im Docker-Image, Video-Thumbnails (extract_video_thumb, poster-Attribut) - Google Analytics entfernt, Umami self-hosted eingebunden (index.html, datenschutz.js) - Admin-Panel Analytics-Tab: Stat-Cards, Sparkline 7 Tage, Top-Seiten (Umami-API-Proxy) - Admin-Panel Tab-Icons korrigiert (aus vorhandenem Phosphor-Sprite) - users.real_name Spalte: Username öffentlich, echter Name privat und optional - Registrierung: Label "Benutzername", Leerzeichen verboten, Profanity-Blockliste - Datenschutzerklärung: GA-Abschnitt durch Umami-Text ersetzt
This commit is contained in:
parent
9a78121a3e
commit
5141ba9969
20 changed files with 524 additions and 143 deletions
101
backend/migrate_media.py
Normal file
101
backend/migrate_media.py
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
"""
|
||||
Einmalige Migration: MOV/AVI/M4V → MP4, HEIC/HEIF → JPEG
|
||||
Alle betroffenen Dateien auf Disk konvertieren + DB-URLs aktualisieren.
|
||||
|
||||
Ausführen im Container:
|
||||
python3 /app/migrate_media.py
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
from database import db
|
||||
from media_utils import convert_media
|
||||
|
||||
MEDIA_DIR = os.getenv("MEDIA_DIR", "/data/media")
|
||||
CONVERT_EXTS = {".mov", ".avi", ".m4v", ".heic", ".heif"}
|
||||
|
||||
|
||||
def _new_ext(ext: str) -> str:
|
||||
return ".mp4" if ext in {".mov", ".avi", ".m4v"} else ".jpg"
|
||||
|
||||
|
||||
def convert_file(path: str) -> str | None:
|
||||
"""Convert file in-place, return new path or None on failure."""
|
||||
ext = os.path.splitext(path)[1].lower()
|
||||
if ext not in CONVERT_EXTS:
|
||||
return None
|
||||
print(f" Konvertiere: {path}")
|
||||
with open(path, "rb") as f:
|
||||
data = f.read()
|
||||
converted, new_ext = convert_media(data, os.path.basename(path))
|
||||
if new_ext == ext:
|
||||
print(f" ✗ Konvertierung fehlgeschlagen, übersprungen.")
|
||||
return None
|
||||
new_path = path[: -len(ext)] + new_ext
|
||||
with open(new_path, "wb") as f:
|
||||
f.write(converted)
|
||||
os.unlink(path)
|
||||
print(f" ✓ → {new_path}")
|
||||
return new_path
|
||||
|
||||
|
||||
def url_from_path(path: str) -> str:
|
||||
rel = os.path.relpath(path, MEDIA_DIR)
|
||||
return "/media/" + rel.replace(os.sep, "/")
|
||||
|
||||
|
||||
def update_db(old_url: str, new_url: str) -> int:
|
||||
updates = 0
|
||||
with db() as conn:
|
||||
# diary_media
|
||||
r = conn.execute("UPDATE diary_media SET url=? WHERE url=?", (new_url, old_url))
|
||||
updates += r.rowcount
|
||||
|
||||
# JSON-Arrays: forum_threads, forum_posts, routes
|
||||
for table, col in [("forum_threads", "foto_urls"),
|
||||
("forum_posts", "foto_urls"),
|
||||
("routes", "foto_urls")]:
|
||||
rows = conn.execute(f"SELECT id, {col} FROM {table} WHERE {col} LIKE ?",
|
||||
(f"%{old_url}%",)).fetchall()
|
||||
for row in rows:
|
||||
urls = json.loads(row[col] or "[]")
|
||||
new_urls = [new_url if u == old_url else u for u in urls]
|
||||
conn.execute(f"UPDATE {table} SET {col}=? WHERE id=?",
|
||||
(json.dumps(new_urls), row["id"]))
|
||||
updates += 1
|
||||
|
||||
# Einzelne URL-Felder
|
||||
for table, col in [("lost_dogs", "foto_url"), ("poison", "foto_url")]:
|
||||
r = conn.execute(f"UPDATE {table} SET {col}=? WHERE {col}=?",
|
||||
(new_url, old_url))
|
||||
updates += r.rowcount
|
||||
|
||||
return updates
|
||||
|
||||
|
||||
def main():
|
||||
total_files = 0
|
||||
total_db = 0
|
||||
|
||||
for root, _, files in os.walk(MEDIA_DIR):
|
||||
for fname in files:
|
||||
ext = os.path.splitext(fname)[1].lower()
|
||||
if ext not in CONVERT_EXTS:
|
||||
continue
|
||||
old_path = os.path.join(root, fname)
|
||||
old_url = url_from_path(old_path)
|
||||
new_path = convert_file(old_path)
|
||||
if new_path:
|
||||
new_url = url_from_path(new_path)
|
||||
n = update_db(old_url, new_url)
|
||||
print(f" DB: {n} Zeile(n) aktualisiert ({old_url} → {new_url})")
|
||||
total_files += 1
|
||||
total_db += n
|
||||
|
||||
print(f"\n✓ Fertig: {total_files} Datei(en) konvertiert, {total_db} DB-Einträge aktualisiert.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue