// backend\main.go package main import ( "context" "encoding/json" "log" "net/http" "os" "strings" "github.com/jackc/pgx/v5/pgxpool" "github.com/joho/godotenv" ) func main() { if err := godotenv.Load(); err != nil { log.Println("Keine .env Datei gefunden, nutze System-Environment oder Fallbacks") } port := env("PORT", "8080") databaseURL := env("DATABASE_URL", "postgres://postgres:postgres@localhost:5432/teg?sslmode=disable") jwtSecret := env("JWT_SECRET", "dev-secret-change-me") frontendOrigin := env("FRONTEND_ORIGIN", "http://localhost:5173") ctx := context.Background() db, err := pgxpool.New(ctx, databaseURL) if err != nil { log.Fatal(err) } defer db.Close() if err := db.Ping(ctx); err != nil { log.Fatal(err) } if err := ensureRuntimeDeviceSchema(ctx, db); err != nil { log.Fatal(err) } server := NewServer(db, jwtSecret, frontendOrigin) server.startPresenceMonitor(ctx) server.startDisappearingMessagesMonitor(ctx) if !server.webPushConfigured() { log.Println("Web Push ist nicht konfiguriert. VAPID_PUBLIC_KEY und VAPID_PRIVATE_KEY sowie eine Absenderadresse fehlen.") } log.Printf("Backend läuft auf http://localhost:%s", port) if err := http.ListenAndServe(":"+port, server.Routes()); err != nil { log.Fatal(err) } } func readJSON(r *http.Request, target any) error { return json.NewDecoder(r.Body).Decode(target) } func writeJSON(w http.ResponseWriter, status int, payload any) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) _ = json.NewEncoder(w).Encode(payload) } func writeError(w http.ResponseWriter, status int, message string) { writeJSON(w, status, map[string]string{ "error": message, }) } func normalizeEmail(email string) string { return strings.ToLower(strings.TrimSpace(email)) } func env(key string, fallback string) string { value := os.Getenv(key) if value == "" { return fallback } return value }