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:
@@ -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())
|
||||
Reference in New Issue
Block a user