Session 2026-04-21: SEO, Wiki-Anreicherung, Training, Lober

SEO & Crawler:
- robots.txt, llms.txt, sitemap.xml (508 Seiten bei Google)
- SSR-Seiten: /info, /wiki/rassen, /wiki/rasse/{slug}, /knigge
- Open Graph, JSON-LD, Breadcrumbs in index.html

Navigation:
- Training unter "Mein Hund", Wissen collapsible
- Welcome-Seite und Landing-Page auf 5-Gruppen-Struktur

Wiki:
- KI-Anreicherung (Claude API): beschreibung, vorkommen_de, Steckbrief
- "So einen hab ich" / Züchter-Verzeichnis
- Scheduler: 50 Rassen beim Start, 20/Nacht

Training:
- Session-Logging (Erfolgsquote, Stimmung, Zufriedenheit)
- Virtueller KI-Trainer (6h-Cache)
- Trainingskalender (Habit-Tracker)
- Top-Training → automatischer Tagebucheintrag
- Gamification ohne Druck: Badges, Streak, Stats

Fortschritts-Lober:
- Jeden Montag 09:00: Claude schreibt Lob-Text pro Hund
- Push + Karte im Tagebuch

Monitoring:
- 4× täglich Status-Mail mit Scheduler-Status + Wiki-Fortschritt
This commit is contained in:
rene 2026-04-21 19:38:20 +02:00
parent 65d1cf6c7f
commit 180de32e57
22 changed files with 4351 additions and 189 deletions

View file

@ -86,6 +86,9 @@ class UserPatch(BaseModel):
is_banned: Optional[int] = None
ban_reason: Optional[str] = None
class WikiEnrichBody(BaseModel):
limit: int = 10
class ThreadAdminPatch(BaseModel):
is_pinned: Optional[int] = None
is_locked: Optional[int] = None
@ -550,3 +553,33 @@ async def get_analytics(user=Depends(require_mod)):
"pageviews": r_pv.json(),
"top_pages": _to_list(r_pages),
}
# ------------------------------------------------------------------
# POST /api/admin/wiki/enrich — KI-Rassen-Anreicherung anstoßen
# ------------------------------------------------------------------
@router.post("/wiki/enrich")
async def wiki_enrich(data: WikiEnrichBody, user=Depends(require_mod)):
from scraper.breed_enricher import enrich_breeds
limit = max(1, min(data.limit, 100))
enriched = await enrich_breeds(limit)
with db() as conn:
remaining = conn.execute(
"SELECT COUNT(*) FROM wiki_rassen WHERE ki_enriched=0"
).fetchone()[0]
return {"enriched": enriched, "remaining": remaining}
# ------------------------------------------------------------------
# DELETE /api/admin/wiki/zuchter/{id} — Züchter-Eintrag löschen (Admin/Mod)
# ------------------------------------------------------------------
@router.delete("/wiki/zuchter/{zuchter_id}", status_code=204)
async def admin_delete_zuchter(zuchter_id: int, user=Depends(require_mod)):
with db() as conn:
row = conn.execute(
"SELECT id FROM wiki_zuchter WHERE id=?", (zuchter_id,)
).fetchone()
if not row:
raise HTTPException(404, "Züchter nicht gefunden.")
conn.execute("DELETE FROM wiki_zuchter WHERE id=?", (zuchter_id,))
_audit(conn, user, "wiki_zuchter_delete", f"zuchter:{zuchter_id}")