managarten/services/mana-events/src/index.ts
Till JS b5d55fdb21 feat(events): add Event Discovery — Phase 1 + 2
Phase 1: Manual iCal feeds + Discovery tab
- 5 new DB tables in event_discovery schema (regions, interests,
  sources, discovered_events, user_actions)
- iCal parser (node-ical) with deduplication (SHA-256 hash)
- Crawl scheduler (15-min interval, auto-deactivate after 5 errors)
- CRUD routes for regions, interests, sources + paginated feed endpoint
- Frontend: "Meine Events" / "Entdecken" tab navigation in ListView
- Discovery setup wizard (regions via mana-geocoding + interests)
- DiscoveredEventCard with save/dismiss, SourceManager for iCal feeds
- "Merken" creates a local socialEvent from discovered event

Phase 2: Auto source discovery + LLM extraction + relevance scoring
- Source discoverer: web search via mana-research to auto-find iCal
  feeds and venue websites for a region
- Website extractor: crawl via mana-research /extract, then LLM-based
  event extraction via mana-llm with structured JSON output
- Flexible date parsing (ISO, DD.MM.YYYY), markdown fence stripping
- Relevance scorer: category match, freetext match, haversine distance,
  time proximity, weekend bonus (0-100 clamped)
- Routes: POST regions/:id/discover-sources, PUT/DELETE sources/:id/activate|reject
- Frontend: "Automatisch finden" button, suggested vs active sources UI

107 tests (all passing), no regressions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-18 15:30:46 +02:00

37 lines
1.2 KiB
TypeScript

/**
* mana-events — Public RSVP & event sharing service.
*
* Hono + Bun runtime. Stores published event snapshots and the public
* RSVP responses they collect. Hosts authenticate via mana-auth JWT;
* RSVP endpoints are intentionally unauthenticated so anyone with a
* share link can respond.
*
* The Hono app itself lives in app.ts so unit tests can import it
* without triggering the production bootstrap (sweeper, log, port).
*/
import { createApp } from './app';
import { loadConfig } from './config';
import { getDb } from './db/connection';
import { startRateBucketSweeper } from './lib/cleanup';
import { startCrawlScheduler } from './discovery/crawl-scheduler';
const config = loadConfig();
const db = getDb(config.databaseUrl);
// Background cleanup of stale rate-limit buckets so they don't
// accumulate for the lifetime of long-published events.
startRateBucketSweeper(db);
// Event discovery — crawl sources (iCal feeds, websites) every 15 minutes.
startCrawlScheduler(db, {
manaResearchUrl: config.manaResearchUrl,
manaLlmUrl: config.manaLlmUrl,
});
console.log(`mana-events starting on port ${config.port}...`);
export default {
port: config.port,
fetch: createApp(db, config).fetch,
};