Initial commit: Filebot Media Browser

Vue 3 + FastAPI Webapp zur Anzeige von Filebot/n8n-Medienmetadaten aus PostgreSQL.
Enthält Frontend, API, Nginx-Config, SQL-Migrationen und Docker-Compose-Setup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Housemann
2026-07-11 05:38:37 +02:00
co-authored by Claude Sonnet 4.6
commit 3f253ffe81
45 changed files with 4791 additions and 0 deletions
+97
View File
@@ -0,0 +1,97 @@
#!/usr/bin/env python3
"""Tabellen auflisten. Im Container: python /app/scripts/list-tables.py"""
import asyncio
import sys
from pathlib import Path
import asyncpg
import yaml
async def list_tables(conn: asyncpg.Connection, db_name: str, schema_hint: str, table_hint: str) -> None:
rows = await conn.fetch(
"""
SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_type = 'BASE TABLE'
AND table_schema NOT IN ('pg_catalog', 'information_schema')
ORDER BY table_schema, table_name
"""
)
print(f"\n=== Datenbank: {db_name} ({len(rows)} Tabellen) ===")
if not rows:
print(" (leer keine Benutzer-Tabellen)")
return
for r in rows:
mark = ""
if r["table_schema"] == schema_hint and r["table_name"] == table_hint:
mark = " <-- Config-Ziel"
print(f" {r['table_schema']}.{r['table_name']}{mark}")
async def main() -> None:
config_path = Path(sys.argv[1] if len(sys.argv) > 1 else "/app/config/config.yaml")
raw = yaml.safe_load(config_path.read_text(encoding="utf-8")) or {}
c = raw.get("database", raw)
schema_hint = c.get("db_schema") or c.get("schema") or "public"
table_hint = c.get("table", "")
print(f"Host: {c['host']}:{c['port']}")
print(f"Config: DB={c['name']} Schema={schema_hint} Tabelle={table_hint}")
# Konfigurierte Datenbank
conn = await asyncpg.connect(
host=c["host"],
port=c["port"],
database=c["name"],
user=c["user"],
password=c["password"],
)
await list_tables(conn, c["name"], schema_hint, table_hint)
await conn.close()
# Alle Datenbanken auflisten und nach filebot-Tabellen suchen
print("\n=== Suche 'filebot' in allen Datenbanken ===")
admin = await asyncpg.connect(
host=c["host"],
port=c["port"],
database="postgres",
user=c["user"],
password=c["password"],
)
dbs = await admin.fetch(
"SELECT datname FROM pg_database WHERE datistemplate = false ORDER BY datname"
)
for db in dbs:
name = db["datname"]
if name in ("template0", "template1"):
continue
try:
c2 = await asyncpg.connect(
host=c["host"],
port=c["port"],
database=name,
user=c["user"],
password=c["password"],
)
hits = await c2.fetch(
"""
SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_type = 'BASE TABLE'
AND table_name ILIKE '%filebot%'
ORDER BY 1, 2
"""
)
if hits:
print(f"\n DB '{name}':")
for h in hits:
print(f" {h['table_schema']}.{h['table_name']}")
await c2.close()
except Exception as exc:
print(f" DB '{name}': kein Zugriff ({exc})")
await admin.close()
if __name__ == "__main__":
asyncio.run(main())