package main import ( "flag" "io/ioutil" "log" "time" "golang.org/x/oauth2/google" "google.golang.org/api/calendar/v3" ) var calName = flag.String("calendar", "", "name of calendar") var days = flag.Int("days", 0, "number of days in the future") func main() { flag.Parse() b, err := ioutil.ReadFile("credentials.json") if err != nil { log.Fatal(err) } // If modifying these scopes, delete your previously saved token.json. config, err := google.ConfigFromJSON(b, calendar.CalendarScope) if err != nil { log.Fatal(err) } client, err := getClient(config) if err != nil { log.Fatal(err) } srv, err := calendar.New(client) if err != nil { log.Fatal(err) } calendars, err := srv.CalendarList.List().Do() if err != nil { log.Fatal(err) } var myCal *calendar.CalendarListEntry for _, item := range calendars.Items { if item.Summary == *calName { myCal = item break } } if myCal == nil { log.Fatalf("calendar '%s' not found", *calName) } loc, err := time.LoadLocation("US/Pacific") if err != nil { log.Fatal(err) } now := time.Now().In(loc) for i := 0; i < *days; i++ { date := now.Add(time.Duration(i * 24) * time.Hour) eventMap, err := getDayEvents(srv, myCal.Id, date) if err != nil { log.Fatal(err) } for _, class := range classes { if !class.happensOnDay(date) { continue } if !class.tagsMatch(date) { continue } ev := class.buildEvent(date) old := eventMap[ev.Summary] if old == nil { log.Printf("add: [%s] %s", ev.Start.DateTime, ev.Summary) _, err := srv.Events.Insert(myCal.Id, ev).Do() if err != nil { log.Fatal(err) } } else { if !eventsEqual(old, ev) { log.Printf("upd: [%s] %s", ev.Start.DateTime, ev.Summary) _, err := srv.Events.Update(myCal.Id, old.Id, ev).Do() if err != nil { log.Fatal(err) } } } } } } func getDayEvents(srv *calendar.Service, calendarId string, t time.Time) (map[string]*calendar.Event, error) { start := time.Date( t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()) // This may be wrong for DST changes, but it's the middle of the night and probably doesn't matter end := start.Add(24 * time.Hour) events, err := srv.Events.List(calendarId). ShowDeleted(false). SingleEvents(true). TimeMin(start.Format(time.RFC3339)). TimeMax(end.Format(time.RFC3339)). MaxResults(250). Do() if err != nil { return nil, err } eventMap := map[string]*calendar.Event{} for _, item := range events.Items { eventMap[item.Summary] = item } return eventMap, nil } func eventsEqual(a *calendar.Event, b *calendar.Event) bool { if a.Summary != b.Summary { return false } if a.Description != b.Description { return false } if a.Start.DateTime[:19] != b.Start.DateTime[:19] { return false } if a.End.DateTime[:19] != b.End.DateTime[:19] { return false } if len(a.Attendees) != len(b.Attendees) { return false } emails := map[string]bool{} for _, attendee := range a.Attendees { emails[attendee.Email] = true } for _, attendee := range b.Attendees { if !emails[attendee.Email] { return false } } return true }