package main import ( "fmt" "github.com/spf13/cobra" "log" "os" "time" ) func main() { rootCmd := &cobra.Command{ Use: "calanonsync", Short: "Synchronize a calendar from EWS to CalDAV by event time and an anonymized title only.", Run: runSynchronization, } rootCmd.AddCommand(InitSettingsCmd()) if err := rootCmd.Execute(); err != nil { fmt.Println(err) os.Exit(1) } } func runSynchronization(cmd *cobra.Command, args []string) { s := LoadSettings() e := NewEWSCalendar(s.EWS.URL, s.EWS.Username, s.EWS.Password) id, err := e.getCalendarFolderID() if err != nil { log.Fatalln(err) } items, err := e.getCalendarItems(id, time.Now().AddDate(0, -1, 0), // One month past time.Now().AddDate(0, 2, 0)) // Two months ahead if err != nil { log.Fatalf("Could not get EWS items: %s\n", err) } relevantEWSItems := make(map[string]CalendarItem) for _, item := range items { // Ignore private items. if item.Sensitivity != "Private" && !item.IsCancelled() { // None-private items though ... remember them by hash. // The hash will equal the CalDAV UID (and its filename). relevantEWSItems[item.Hash()] = item } } c := NewCalDAV(s.CalDAV) calDavItems, err := c.GetEvents() if err != nil { log.Fatalf("Could not get CalDAV items: %s\n", err) } // Build a map for easier lookup by UID calDavItemMap := make(map[string]CalDAVItem) for _, item := range calDavItems { calDavItemMap[item.UID()] = item } // First step: find items that were changed or that were removed // and update the CalDAV side accordingly. for uid, calDavItem := range calDavItemMap { if ewsItem, ok := relevantEWSItems[uid]; ok { // Good, so we still know the item at least. if !ewsItem.Start.Equal(calDavItem.Start()) || !ewsItem.End.Equal(calDavItem.End()) { // So times have changed. Update. calDavItem.Update(ewsItem.Start, ewsItem.End, ewsItem.IsAllDayEvent) err := c.UploadItem(calDavItem) if err == nil { log.Printf("Updated item %s (%s)\n", uid, ewsItem.Subject) } else { // Not fatal, but worth a note. log.Println(err) } } } else { // Oops, seems the item vanished. err := c.DeleteItem(calDavItem) if err == nil { log.Printf("Deleted item %s (%s)\n", calDavItem.UID(), calDavItem.Summary()) } else { // Not fatal, but worth a note. log.Println(err) } } } // Find items we don't know so far and create them. for uid, ewsItem := range relevantEWSItems { if _, ok := calDavItemMap[uid]; !ok { title := s.Anonymize.Title.Apply(ewsItem.Subject) ical := CreateICal(ewsItem.Hash(), title, ewsItem.Start, ewsItem.End, ewsItem.IsAllDayEvent) calDavItem := CalDAVItem{HRef: uid + ".ics", ICal: ical} err := c.UploadItem(calDavItem) if err == nil { log.Printf("Created item %s (%s)\n", uid, ewsItem.Subject) } else { log.Println(err) } } } }