Some checks are pending
CI / validate (push) Waiting to run
Lücken-Analyse gegen party-news.de zeigte: Venues, die wir crawlen
könnten, fehlten oder hatten tote/keine Quellen.
- grey-konstanz: eventSource-URL von greyclub.de/events (404) auf die
Startseite grey-konstanz.de korrigiert (rendert die Events inline).
- logans-city-konstanz, vauna-vlora-konstanz, pfiff-konstanz: neu
kuratiert (Adresse/Geo gegen Primärquellen + Nominatim verifiziert,
Beschreibungen als Kurz-Zitat ≤200 Zeichen, Compliance-Veto ✅).
pfiff websiteUrl=null, da pfiff-konstanz.de eine Casino-Spam-
Domain-Übernahme ist. Keine der drei hat eine crawlbare Programm-
Seite → Anker für city-scope/Submission.
- docs/CITY_SOURCE_KONSTANZ.md: Runbook für die scope='city'-Quelle
veranstaltungen.konstanz.de/region/ (offizieller MTK-Kalender,
robots-geprüft) — Anlage via Admin-API, da city-Quellen keinen
YAML-Pfad haben.
Quellen als Lead aus party-news.de, jede gegen die Primärquelle
verifiziert; keine Event-Inhalte/DB-Teile übernommen (AGGREGATOR_POLICY).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
90 lines
4.1 KiB
Markdown
90 lines
4.1 KiB
Markdown
# City-Scope-Quelle Konstanz — Runbook
|
|
|
|
Wie der stadtweite Sammelkalender für Konstanz als `scope='city'`-
|
|
Event-Quelle angelegt, geprüft und aktiviert wird.
|
|
|
|
> **Warum kein YAML?** Anders als Venue-Quellen (`scope='venue'`, kuratiert
|
|
> als YAML in `apps/api/src/data/curated/venues/<slug>.yml` mit
|
|
> `eventSource:`-Block) werden **city-Quellen bewusst nur über die
|
|
> Admin-API** angelegt — siehe [`CURATOR.md`](./CURATOR.md). Ein
|
|
> stadtweiter Kalender ist keine Venue, deshalb gibt es keinen Import-Pfad.
|
|
|
|
## Verifizierte Quelle
|
|
|
|
| Feld | Wert |
|
|
|---|---|
|
|
| `url` | `https://veranstaltungen.konstanz.de/region/` |
|
|
| `city` | `Konstanz` |
|
|
| `regionSlug` | `bodensee` |
|
|
| `countryCode` | `DE` |
|
|
| `parserHint` | `firecrawl-llm` (Default — Seite ist server-rendertes HTML ohne JSON-LD) |
|
|
| `crawlIntervalHours` | `24` (Default) |
|
|
|
|
**Quelle ist der offizielle MTK / Stadt-Konstanz-Tourismuskalender**, kein
|
|
kommerzieller Mitbewerber-Aggregator. Geprüft am 2026-06-05:
|
|
|
|
- **robots.txt** (`veranstaltungen.konstanz.de`): `User-agent: *` blockt
|
|
nur Infra-Pfade (`/includes/`, `/export/`, `/apps/`, `/login/` …);
|
|
`/region/` ist **erlaubt**, kein Crawl-Delay gesetzt → unser
|
|
`SEEPULS_CRAWL_INTERVAL_MS` (≥ 1,1 s) reicht (AGGREGATOR_POLICY §1).
|
|
- **Inhalt**: rendert datierte Events server-seitig (HTML, kein JS nötig);
|
|
am Prüftag 17 Datums-Vorkommen ab heute auf der ersten Seite.
|
|
- **Abdeckung**: ganze Region → löst bestehende Venues auf
|
|
(Logan's/Pfiff/Vauna …) und legt für unbekannte Orte automatisch
|
|
`pending-review`-Venues an (Reviewer-Gate).
|
|
|
|
Verworfen: `www.konstanz.de/.../veranstaltungskalender` (Stadt-Verwaltung)
|
|
hat `Crawl-delay: 30` → zu zäh für den gleichen Inhalt.
|
|
|
|
## Anlage-Sequenz
|
|
|
|
Die Admin-Routen unter `/api/v1/admin/*` sind per `jwtAuth()` geschützt —
|
|
**braucht ein gültiges mana-auth-Admin-JWT** (kein Service-Key).
|
|
|
|
```bash
|
|
API=https://api.seepuls.com
|
|
TOKEN=<dein mana-auth Admin-JWT>
|
|
|
|
# 1 — anlegen (startet inaktiv: active=false)
|
|
curl -s -X POST "$API/api/v1/admin/event-sources" \
|
|
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
|
|
-d '{"url":"https://veranstaltungen.konstanz.de/region/","city":"Konstanz","regionSlug":"bodensee","countryCode":"DE"}'
|
|
# → {"id":"es_…","scope":"city","active":false,"next_step":"probe-then-activate"}
|
|
|
|
# 2 — Probe: Preview OHNE DB-Write (newItems=0), zeigt extrahierte Events
|
|
# inkl. gelesenem venue_name/venue_address (Auflösung erst beim echten Run)
|
|
curl -s -X POST "$API/api/v1/admin/event-sources/<id>/probe" \
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
| jq '.preview[] | {title, starts_at, venue_name, venue_address}'
|
|
|
|
# 3 — wenn die Probe stimmt: scharf schalten
|
|
curl -s -X PATCH "$API/api/v1/admin/event-sources/<id>" \
|
|
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
|
|
-d '{"active":true}'
|
|
|
|
# (optional) sofortiger Crawl statt auf den 24h-Cron warten:
|
|
curl -s -X POST "$API/api/v1/admin/event-sources/<id>/run" \
|
|
-H "Authorization: Bearer $TOKEN" | jq
|
|
```
|
|
|
|
## Reihenfolge & Folgewirkung — vor dem Aktivieren beachten
|
|
|
|
1. **Erst Venue-Import, dann city-Quelle.** Die drei kuratierten Venues
|
|
(`logans-city-konstanz`, `vauna-vlora-konstanz`, `pfiff-konstanz`)
|
|
müssen importiert sein (`pnpm --filter ./apps/api db:import-venues`,
|
|
läuft beim Deploy), **bevor** der erste city-Crawl läuft. Sonst legt
|
|
die Venue-Auflösung eigene `pending-review`-Rows an und die Events
|
|
hängen am falschen Ort.
|
|
2. **Moderations-Rückstau.** Ein Regions-Kalender bringt viele neue
|
|
`pending-review`-Venues (alles, was noch nicht kuratiert ist). Gewollt,
|
|
aber jemand muss durchsehen. Die Probe (Schritt 2) zeigt vorher, was
|
|
reinkäme — Sampling-Reviewer-Stop wie im Curator-Workflow.
|
|
|
|
## Compliance
|
|
|
|
city-Crawl unterliegt der vollen [`AGGREGATOR_POLICY`](../../mana/docs/AGGREGATOR_POLICY.md):
|
|
robots.txt-Lookup pro Crawl (geloggt in `crawl_jobs.robots_check_passed`),
|
|
≥ 1,1 s Delay, User-Agent mit Kontakt-Mail, sichtbare Attribution
|
|
(Quell-Domain + `accessedOn`) im Frontend, Take-Down-Endpoint. Vor dem
|
|
Live-Cut: `mana-compliance`-Pre-Live-Veto (steht in AGGREGATOR_POLICY
|
|
„Offene Punkte").
|