package main import ( "fmt" "time" "github.com/fatih/color" calendar "google.golang.org/api/calendar/v3" ) type Event struct { //Attachments []EventAttachment // Google Drive files Attendees []EventAttendee CalendarId string ColorId string Created string Creator *EventAttendee Description string End *calendar.EventDateTime EndTimeUnspecified bool Etag string //ExtendedProperties []EventExtendedProperties GuestsCanInviteOthers bool GuestsCanModify bool GuestsCanSeeOtherGuests bool HangoutLink string HtmlLink string ICalUID string Id string Kind string Location string Locked bool Organizer *EventAttendee OriginalStartTime *calendar.EventDateTime PrivateCopy bool Recurrence []string RecurringEventId string //Reminders *EventReminders Sequence int64 //Source *EventSource Start *calendar.EventDateTime Status string Summary string Transparency string Updated string Visibility string // The instance id is the id by which the user can refer to this event InstanceId int } func (e *Event) IsAllDayEvent() bool { _, err := time.Parse(time.RFC3339, e.Start.DateTime) return err != nil } func (e *Event) GetColorizedDateTimeString() string { if e.IsAllDayEvent() { return color.New(color.FgGreen).Sprint("[== All Day ==]") } tmString := e.GetStartTimeString() + " - " + e.GetEndTimeString() if time.Until(e.GetStartTime()) < 0 && time.Until(e.GetEndTime()) < 0 { // Event is in the past return color.New(color.FgHiBlack).Add(color.Faint).Sprint("[" + tmString + "]") } else if time.Until(e.GetStartTime()) < 0 && time.Until(e.GetEndTime()) > 0 { // Event is NOW return color.New(color.FgRed).Add(color.Bold).Sprint("[" + tmString + "]") } else if time.Until(e.GetStartTime()) < time.Hour { // Event is in less than an hour return color.New(color.FgYellow).Add(color.Bold).Sprint("[" + tmString + "]") } return "[" + tmString + "]" } func (e *Event) ToCLIString() string { return fmt.Sprintf("%s\n%s\n", e.Summary, e.GetStartTime()) } func (e *Event) GetStartTimeString() string { tm, err := time.Parse(time.RFC3339, e.Start.DateTime) if err != nil { return "--:--" } return tm.Local().Format("15:04") } func (e *Event) GetStartTime() time.Time { tm, _ := time.Parse(time.RFC3339, e.Start.DateTime) return tm.Local() } func (e *Event) GetEndTimeString() string { tm, err := time.Parse(time.RFC3339, e.End.DateTime) if err != nil { return "00:00" } return tm.Local().Format("15:04") } func (e *Event) GetEndTime() time.Time { tm, _ := time.Parse(time.RFC3339, e.End.DateTime) return tm.Local() } func GoogleEventToLocalWithId(e *calendar.Event, cId string) *Event { ret := GoogleEventToLocal(e) ret.CalendarId = cId return ret } func GoogleEventToLocal(e *calendar.Event) *Event { return &Event{ //Attachments []EventAttachment // Google Drive files Attendees: GoogleAttendeeSliceToLocal(e.Attendees), ColorId: e.ColorId, Created: e.Created, Creator: GoogleCreatorToLocal(e.Creator), Description: e.Description, End: e.End, EndTimeUnspecified: e.EndTimeUnspecified, Etag: e.Etag, //ExtendedProperties []EventExtendedProperties //GuestsCanInviteOthers: *e.GuestsCanInviteOthers, GuestsCanModify: e.GuestsCanModify, //GuestsCanSeeOtherGuests: *e.GuestsCanSeeOtherGuests, HangoutLink: e.HangoutLink, HtmlLink: e.HtmlLink, ICalUID: e.ICalUID, Id: e.Id, Kind: e.Kind, Location: e.Location, Locked: e.Locked, Organizer: GoogleOrganizerToLocal(e.Organizer), OriginalStartTime: e.OriginalStartTime, PrivateCopy: e.PrivateCopy, Recurrence: e.Recurrence, RecurringEventId: e.RecurringEventId, //Reminders *EventReminders Sequence: e.Sequence, //Source *EventSource Start: e.Start, Status: e.Status, Summary: e.Summary, Transparency: e.Transparency, Updated: e.Updated, Visibility: e.Visibility, } } func LocalEventToGoogle(e *Event) *calendar.Event { return &calendar.Event{ //Attachments []EventAttachment // Google Drive files //Attendees: GoogleAttendeeSliceToLocal(e.Attendees), ColorId: e.ColorId, Created: e.Created, Creator: LocalCreatorToGoogle(e.Creator), Description: e.Description, End: e.End, EndTimeUnspecified: e.EndTimeUnspecified, Etag: e.Etag, //ExtendedProperties []EventExtendedProperties //GuestsCanInviteOthers: *e.GuestsCanInviteOthers, GuestsCanModify: e.GuestsCanModify, //GuestsCanSeeOtherGuests: *e.GuestsCanSeeOtherGuests, HangoutLink: e.HangoutLink, HtmlLink: e.HtmlLink, ICalUID: e.ICalUID, Id: e.Id, Kind: e.Kind, Location: e.Location, Locked: e.Locked, Organizer: LocalOrganizerToGoogle(e.Organizer), OriginalStartTime: e.OriginalStartTime, PrivateCopy: e.PrivateCopy, Recurrence: e.Recurrence, RecurringEventId: e.RecurringEventId, //Reminders *EventReminders Sequence: e.Sequence, //Source *EventSource Start: e.Start, Status: e.Status, Summary: e.Summary, Transparency: e.Transparency, Updated: e.Updated, Visibility: e.Visibility, } } type EventAttendee struct { AdditionalGuests int64 Comment string DisplayName string Email string Id string Optional bool Organizer bool Resource bool ResponseStatus string Self bool EventCreator bool EventOrganizer bool } func GoogleAttendeeSliceToLocal(a []*calendar.EventAttendee) []EventAttendee { var ret []EventAttendee for _, e := range a { ret = append(ret, *GoogleAttendeeToLocal(e)) } return ret } func LocalAttendeeSliceToGoogle(a []EventAttendee) []*calendar.EventAttendee { var ret []*calendar.EventAttendee for _, e := range a { ret = append(ret, LocalAttendeeToGoogle(&e)) } return ret } func GoogleAttendeeToLocal(a *calendar.EventAttendee) *EventAttendee { return &EventAttendee{ AdditionalGuests: a.AdditionalGuests, Comment: a.Comment, DisplayName: a.DisplayName, Email: a.Email, Id: a.Id, Optional: a.Optional, Organizer: a.Organizer, Resource: a.Resource, ResponseStatus: a.ResponseStatus, Self: a.Self, } } func LocalAttendeeToGoogle(a *EventAttendee) *calendar.EventAttendee { return &calendar.EventAttendee{ AdditionalGuests: a.AdditionalGuests, Comment: a.Comment, DisplayName: a.DisplayName, Email: a.Email, Id: a.Id, Optional: a.Optional, Organizer: a.Organizer, Resource: a.Resource, ResponseStatus: a.ResponseStatus, Self: a.Self, } } func GoogleOrganizerToLocal(a *calendar.EventOrganizer) *EventAttendee { return &EventAttendee{ DisplayName: a.DisplayName, Email: a.Email, Id: a.Id, Self: a.Self, EventOrganizer: true, } } func LocalOrganizerToGoogle(a *EventAttendee) *calendar.EventOrganizer { return &calendar.EventOrganizer{ DisplayName: a.DisplayName, Email: a.Email, Id: a.Id, Self: a.Self, } } func GoogleCreatorToLocal(a *calendar.EventCreator) *EventAttendee { return &EventAttendee{ DisplayName: a.DisplayName, Email: a.Email, Id: a.Id, Self: a.Self, EventCreator: true, } } func LocalCreatorToGoogle(a *EventAttendee) *calendar.EventCreator { return &calendar.EventCreator{ DisplayName: a.DisplayName, Email: a.Email, Id: a.Id, Self: a.Self, } } type ByStartTime []Event func (a ByStartTime) Len() int { return len(a) } func (a ByStartTime) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByStartTime) Less(i, j int) bool { st1, _ := time.Parse(time.RFC3339, a[i].Start.DateTime) st2, _ := time.Parse(time.RFC3339, a[j].Start.DateTime) return st2.After(st1) }