wannpassts/backend/internal/calendar/provider.go
Tronax cb30223fd4
feat: add WannPassts booking app with Go backend and Vue frontend
Initial project setup for a privacy-focused, self-hosted scheduling app:

- Go backend with JWT auth, SQLite storage, and chi router
- Calendar integrations via Google OAuth (FreeBusy), CalDAV, and ICS links
- Public booking pages with configurable slots and booking requests
- AES-256-GCM encryption for stored provider tokens
- Vue 3 + TypeScript frontend with Vite, Pinia, and Vue Router
- Docs, .gitignore, and .env.example for local development
2026-08-25 18:50:28 +02:00

41 lines
980 B
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package calendar
import (
"context"
"sort"
"time"
)
// Interval ist ein "beschäftigt"-Zeitraum. Enthält bewusst KEINE Termindetails,
// nur Start und Ende mehr verlässt den Kalender des Nutzers nie.
type Interval struct {
Start time.Time
End time.Time
}
type Provider interface {
// FetchBusy liefert alle busy-Zeiträume im Fenster [from, to).
FetchBusy(ctx context.Context, from, to time.Time) ([]Interval, error)
}
// clampIntervals schneidet Intervalle aufs Fenster zurecht, verwirft ungültige
// und sortiert das Ergebnis.
func clampIntervals(in []Interval, from, to time.Time) []Interval {
out := make([]Interval, 0, len(in))
for _, iv := range in {
if !iv.End.After(iv.Start) {
continue
}
if iv.Start.Before(from) {
iv.Start = from
}
if iv.End.After(to) {
iv.End = to
}
if iv.End.After(iv.Start) {
out = append(out, iv)
}
}
sort.Slice(out, func(i, j int) bool { return out[i].Start.Before(out[j].Start) })
return out
}