package jobs import ( "autocal/pkg/autocal" "autocal/services" "strings" "time" "github.com/charmbracelet/log" "google.golang.org/api/calendar/v3" ) // Start jobs func Start(calSrv *calendar.Service, config *autocal.Autocal) { // Setup time t := time.Now().Format(time.RFC3339) // Create events channel events := make(chan *calendar.Event) // Start event watcher go func() { checkForNewEvents(calSrv, config, t, events) }() // Wait for jobs for event := range events { // Loop through rules in config for _, rule := range config.Events { // Check if the event name matches the rule // either by exact name or by keyword isMatch := (rule.ExactName && event.Summary == rule.Name) || (!rule.ExactName && strings.Contains(event.Summary, rule.Name)) if isMatch { if config.Notifications.Logging { log.Info("Found matching event", "event", event.Summary, "rule", rule.Name) } // Add participants to the event go func(e *calendar.Event) { err := addParticipantsToEvent(calSrv, e, &config.Notifications, rule.Participants) if err != nil { log.Error("Failed to add participants", "err", err) } }(event) // Once a rule matches, we can stop checking other rules for this event break } } } } func addParticipantsToEvent(calSrv *calendar.Service, event *calendar.Event, notifications *autocal.Notifications, participants []string) error { // Create a map of existing attendees for quick lookup existingAttendees := make(map[string]bool) for _, attendee := range event.Attendees { existingAttendees[attendee.Email] = true } // Flag to check if we need to update the event shouldUpdate := false // Add new participants if they are not already in the event for _, participant := range participants { if !existingAttendees[participant] { event.Attendees = append(event.Attendees, &calendar.EventAttendee{ Email: participant }) shouldUpdate = true if notifications.Logging { log.Info("Adding new participant", "event", event.Summary, "participant", participant) } } } // If we've added new attendees, update the event in Google Calendar if shouldUpdate { _, err := calSrv.Events.Update("primary", event.Id, event).Do() if err != nil { return err } if notifications.Logging { log.Info("Successfully updated event", "event", event.Summary) } } return nil } // Checks periodically for new events func checkForNewEvents(calSrv *calendar.Service, config *autocal.Autocal, t string, eventsCh chan *calendar.Event) { // Create ticker interval := time.Duration(config.Interval) * time.Minute ticker := time.NewTicker(interval) defer ticker.Stop() // Start loop for { // Get events log.Info("Checking for new events") events, err := services.ListEvents(calSrv, "primary", false, true, t, 10, "startTime") if err != nil { log.Fatal("Failed to fetch events", "err", err) } // Send events if len(events.Items) > 0 { for _, event := range events.Items { eventsCh <- event } // Update the time to the last event checked to avoid processing the same events again t = events.Items[len(events.Items)-1].Created } // Wait for next tick <-ticker.C } }