2017-02-16 15:59:33 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
|
2017-03-16 21:11:39 +00:00
|
|
|
"github.com/fatih/color"
|
|
|
|
|
2017-02-16 15:59:33 +00:00
|
|
|
calendar "google.golang.org/api/calendar/v3"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Event struct {
|
|
|
|
//Attachments []EventAttachment // Google Drive files
|
|
|
|
Attendees []EventAttendee
|
2017-03-15 19:38:37 +00:00
|
|
|
CalendarId string
|
2017-02-16 15:59:33 +00:00
|
|
|
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
|
2017-03-16 21:11:39 +00:00
|
|
|
|
|
|
|
// 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.FgGreen).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 + "]"
|
2017-02-16 15:59:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Event) ToCLIString() string {
|
|
|
|
return fmt.Sprintf("%s\n%s\n", e.Summary, e.GetStartTime())
|
|
|
|
}
|
|
|
|
|
2017-03-02 16:26:34 +00:00
|
|
|
func (e *Event) GetStartTimeString() string {
|
2017-02-16 15:59:33 +00:00
|
|
|
tm, err := time.Parse(time.RFC3339, e.Start.DateTime)
|
|
|
|
if err != nil {
|
2017-03-16 21:11:39 +00:00
|
|
|
return "--:--"
|
2017-02-16 15:59:33 +00:00
|
|
|
}
|
2017-03-15 19:38:37 +00:00
|
|
|
return tm.Local().Format("15:04")
|
2017-02-16 15:59:33 +00:00
|
|
|
}
|
|
|
|
|
2017-03-02 16:26:34 +00:00
|
|
|
func (e *Event) GetStartTime() time.Time {
|
|
|
|
tm, _ := time.Parse(time.RFC3339, e.Start.DateTime)
|
2017-03-23 12:44:45 +00:00
|
|
|
return tm.Local()
|
2017-03-02 16:26:34 +00:00
|
|
|
}
|
|
|
|
|
2017-03-15 19:38:37 +00:00
|
|
|
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)
|
2017-03-23 12:44:45 +00:00
|
|
|
return tm.Local()
|
2017-03-15 19:38:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func GoogleEventToLocalWithId(e *calendar.Event, cId string) *Event {
|
|
|
|
ret := GoogleEventToLocal(e)
|
|
|
|
ret.CalendarId = cId
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2017-02-16 15:59:33 +00:00
|
|
|
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
|
|
|
|
|
2017-03-23 12:44:45 +00:00
|
|
|
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)
|
|
|
|
}
|