summaryrefslogtreecommitdiff
path: root/internal/api
diff options
context:
space:
mode:
Diffstat (limited to 'internal/api')
-rw-r--r--internal/api/google_calendar.go98
-rw-r--r--internal/api/google_calendar_test.go30
-rw-r--r--internal/api/interfaces.go1
3 files changed, 0 insertions, 129 deletions
diff --git a/internal/api/google_calendar.go b/internal/api/google_calendar.go
index bb17812..f441a45 100644
--- a/internal/api/google_calendar.go
+++ b/internal/api/google_calendar.go
@@ -5,7 +5,6 @@ import (
"fmt"
"log"
"sort"
- "strconv"
"strings"
"time"
@@ -84,86 +83,6 @@ func deduplicateEvents(events []models.CalendarEvent) []models.CalendarEvent {
return unique
}
-var recurrenceFreqNames = map[string]string{
- "DAILY": "daily",
- "WEEKLY": "weekly",
- "MONTHLY": "monthly",
- "YEARLY": "yearly",
-}
-
-var recurrenceFreqUnits = map[string]string{
- "DAILY": "day",
- "WEEKLY": "week",
- "MONTHLY": "month",
- "YEARLY": "year",
-}
-
-var recurrenceWeekdayNames = map[string]string{
- "SU": "Sunday",
- "MO": "Monday",
- "TU": "Tuesday",
- "WE": "Wednesday",
- "TH": "Thursday",
- "FR": "Friday",
- "SA": "Saturday",
-}
-
-// formatRecurrence turns Google Calendar RRULE strings into short English.
-// This intentionally covers only the common cases (FREQ, INTERVAL, BYDAY) --
-// not a full RFC 5545 parser. Anything it can't confidently describe falls
-// back to "Recurring event" rather than showing nothing or an error.
-func formatRecurrence(rrules []string) string {
- for _, rule := range rrules {
- rule = strings.TrimPrefix(rule, "RRULE:")
- parts := make(map[string]string)
- for _, kv := range strings.Split(rule, ";") {
- pieces := strings.SplitN(kv, "=", 2)
- if len(pieces) == 2 {
- parts[pieces[0]] = pieces[1]
- }
- }
-
- freqKey := parts["FREQ"]
- unit, ok := recurrenceFreqUnits[freqKey]
- if !ok {
- continue
- }
-
- interval := 1
- if iv := parts["INTERVAL"]; iv != "" {
- if n, err := strconv.Atoi(iv); err == nil && n > 0 {
- interval = n
- }
- }
-
- var phrase string
- if interval == 1 {
- phrase = "Repeats " + recurrenceFreqNames[freqKey]
- } else {
- phrase = fmt.Sprintf("Repeats every %d %ss", interval, unit)
- }
-
- if byday := parts["BYDAY"]; byday != "" {
- var days []string
- for _, code := range strings.Split(byday, ",") {
- code = strings.TrimSpace(code)
- if len(code) >= 2 {
- code = code[len(code)-2:]
- }
- if name, ok := recurrenceWeekdayNames[code]; ok {
- days = append(days, name)
- }
- }
- if len(days) > 0 {
- phrase += " on " + strings.Join(days, ", ")
- }
- }
-
- return phrase
- }
- return "Recurring event"
-}
-
// NewGoogleCalendarClient creates a client that fetches from multiple calendars.
// calendarIDs can be comma-separated (e.g., "cal1@group.calendar.google.com,cal2@group.calendar.google.com")
// timezone is the IANA timezone name for display (e.g., "Pacific/Honolulu")
@@ -285,20 +204,3 @@ func (c *GoogleCalendarClient) GetCalendarList(ctx context.Context) ([]models.Ca
return calendars, nil
}
-// GetRecurrenceRule looks up a recurring event's master record and returns
-// its formatted recurrence schedule. Google's API only puts the RRULE on
-// the master event, not on expanded instances (see parseEventTime's
-// SingleEvents(true) callers), so this does a live lookup by the instance's
-// RecurringEventId. There's no per-event calendar attribution stored today
-// (events from all configured calendars are merged without recording which
-// one they came from), so this tries each configured calendar in turn.
-func (c *GoogleCalendarClient) GetRecurrenceRule(ctx context.Context, recurringEventID string) (string, error) {
- for _, calendarID := range c.calendarIDs {
- event, err := c.srv.Events.Get(calendarID, recurringEventID).Do()
- if err != nil {
- continue
- }
- return formatRecurrence(event.Recurrence), nil
- }
- return "", fmt.Errorf("recurring event %s not found on any configured calendar", recurringEventID)
-}
diff --git a/internal/api/google_calendar_test.go b/internal/api/google_calendar_test.go
index efbab0d..3cf0dbd 100644
--- a/internal/api/google_calendar_test.go
+++ b/internal/api/google_calendar_test.go
@@ -272,33 +272,3 @@ func TestGetUpcomingEvents_APIError_ReturnsEmptyNotError(t *testing.T) {
t.Errorf("expected 0 events on API error, got %d", len(events))
}
}
-
-// --- formatRecurrence ---
-
-func TestFormatRecurrence(t *testing.T) {
- tests := []struct {
- name string
- rules []string
- want string
- }{
- {"weekly single day", []string{"RRULE:FREQ=WEEKLY;BYDAY=MO"}, "Repeats weekly on Monday"},
- {"weekly multiple days", []string{"RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR"}, "Repeats weekly on Monday, Wednesday, Friday"},
- {"daily", []string{"RRULE:FREQ=DAILY"}, "Repeats daily"},
- {"monthly", []string{"RRULE:FREQ=MONTHLY"}, "Repeats monthly"},
- {"yearly", []string{"RRULE:FREQ=YEARLY"}, "Repeats yearly"},
- {"interval weekly", []string{"RRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=SU"}, "Repeats every 2 weeks on Sunday"},
- {"interval daily", []string{"RRULE:FREQ=DAILY;INTERVAL=3"}, "Repeats every 3 days"},
- {"unrecognized frequency", []string{"RRULE:FREQ=HOURLY"}, "Recurring event"},
- {"empty", []string{}, "Recurring event"},
- {"unparseable", []string{"not a valid rule"}, "Recurring event"},
- }
-
- for _, tc := range tests {
- t.Run(tc.name, func(t *testing.T) {
- got := formatRecurrence(tc.rules)
- if got != tc.want {
- t.Errorf("formatRecurrence(%v) = %q, want %q", tc.rules, got, tc.want)
- }
- })
- }
-}
diff --git a/internal/api/interfaces.go b/internal/api/interfaces.go
index 3c1e4e1..183f3f0 100644
--- a/internal/api/interfaces.go
+++ b/internal/api/interfaces.go
@@ -30,7 +30,6 @@ type GoogleCalendarAPI interface {
GetEventsByDateRange(ctx context.Context, start, end time.Time) ([]models.CalendarEvent, error)
GetCalendarList(ctx context.Context) ([]models.CalendarInfo, error)
SetCalendarIDs(ids []string)
- GetRecurrenceRule(ctx context.Context, recurringEventID string) (string, error)
}
// GoogleTasksAPI defines the interface for Google Tasks operations