package main import ( "encoding/json" "fmt" "io/ioutil" "log" "os" "strings" "time" "github.com/br0xen/user-config" "github.com/fatih/color" ) const ( AppName = "galendar" AppVersion = 1 ) type AppState struct { Name string Version int ClientSecret []byte cfg *userConfig.Config account *Account defaultCalendars []string quickAddCalendar string StatusMsg string } var state *AppState func main() { var err error var op string state = &AppState{Name: AppName, Version: AppVersion} state.cfg, err = userConfig.NewConfig(state.Name) if err != nil { panic(err) } if len(os.Args) > 1 { op = os.Args[1] } else { op = "today" } DoVersionCheck() if op == "refresh" { // Invalidate Cache, then just do a 'today' if err = state.cfg.SetDateTime("calListUseBy", time.Now()); err != nil { fmt.Println("cahceInvalidate error:", err) } op = "today" } switch op { case "--reinit": // Reset all config for _, v := range state.cfg.GetKeyList() { fmt.Println("Deleting Key: " + v) state.cfg.DeleteKey(v) } case "today": // Show everything on the calendar for today InitComm() events := state.account.GetTodaysEvents() if len(events) == 0 { fmt.Println("No Events Found") } else { for _, e := range events { isOnCal := false for _, idx := range state.defaultCalendars { if idx == e.CalendarId { isOnCal = true break } } if !isOnCal { continue } stTmStr := e.GetStartTimeString() durStr := "(" + e.GetEndTime().Sub(e.GetStartTime()).String() + ")" if stTmStr == "00:00" { stTmStr = "All Day" durStr = "" } else { stTmStr = " " + stTmStr } eventString := "[" + stTmStr + "] " + e.Summary + " " + durStr if time.Until(e.GetStartTime()) < 0 && time.Until(e.GetEndTime()) < 0 { // Event is in the past color.New(color.FgGreen).Add(color.Bold).Println(eventString) } else if time.Until(e.GetStartTime()) < 0 && time.Until(e.GetEndTime()) > 0 { // Event is NOW color.New(color.FgRed).Add(color.Bold).Println(eventString) } else if time.Until(e.GetStartTime()) < time.Hour { // Event is in less than an hour color.New(color.FgYellow).Add(color.Bold).Println(eventString) } else { fmt.Println(eventString) } } } case "config": // Open the Configuration CUI screen InitComm() DoConfig() case "ui": // Open the UI mode InitComm() DoUIMode() case "defaults": // Show Defaults InitComm() for i := range state.defaultCalendars { fmt.Println(state.defaultCalendars[i]) } case "add": // Quick event add to primary calendar quickAddText := strings.Join(os.Args[2:], " ") InitComm() e, err := state.account.GetDefaultCalendar().QuickAdd(quickAddText) if err != nil { fmt.Println(err.Error()) } else { fmt.Println(e.ToCLIString()) // Invalidate the cache if err = state.cfg.SetDateTime("calListUseBy", time.Now()); err != nil { fmt.Println("cahceInvalidate error:", err) } } case "bail": // Just initialize communications and bail InitComm() } // All done, save the account state saveAccountState() } func InitComm() { var err error sec := state.cfg.GetBytes("ClientSecret") tkn := state.cfg.GetBytes("Token") state.account, err = GetAccount(sec, tkn) if err != nil { log.Fatalf("Unable to get Account: %v", err) } // Save the Raw Token state.cfg.SetBytes("Token", state.account.CC.GetRawToken()) loadAccountState() } func DoVersionCheck() { confVer, _ := state.cfg.GetInt("version") for confVer < state.Version { // Update from confVer to state.Version switch confVer { case 0: // Initializing the app fmt.Println("Initializing gocal") if GoogleClientJson == "" { for { fmt.Println("Client Secret Filename (Ctrl-C to exit): ") var fn string if _, err := fmt.Scan(&fn); err == nil { var b []byte b, err = ioutil.ReadFile(fn) if len(b) > 0 && err == nil { state.cfg.SetBytes("ClientSecret", b) break } } } } else { state.cfg.Set("ClientSecret", GoogleClientJson) } state.cfg.SetInt("version", 1) state.cfg.SetArray("defaultCalendars", []string{"primary"}) state.cfg.Set("quickAddCalendar", "") } state.ClientSecret = state.cfg.GetBytes("ClientSecret") // Refetch the version from the config confVer, _ = state.cfg.GetInt("version") } } // saveAccountState saves all the bits of cache from the account // into our config func saveAccountState() { var err error var calListJson []byte if calListJson, err = json.Marshal(state.account.CalendarList); err == nil { if err = state.cfg.SetBytes("calendarList", calListJson); err != nil { fmt.Println("saveAccountState:calendarList error:", err) } if err = state.cfg.SetDateTime("calListUseBy", state.account.CalListUseBy); err != nil { fmt.Println("saveAccountState:calListUseBy error:", err) } } var evListJson []byte if evListJson, err = json.Marshal(state.account.EventList); err == nil { if err = state.cfg.SetBytes("eventList", evListJson); err != nil { fmt.Println("saveAccountState:eventList error:", err) } if err = state.cfg.SetDateTime("eventListUseBy", state.account.EventListUseBy); err != nil { fmt.Println("saveAccountState:eventListUseBy error:", err) } } if err = state.cfg.SetArray("defaultCalendars", state.defaultCalendars); err != nil { fmt.Println("saveAccountState:defaultCalendars error:", err) } if err = state.cfg.Set("quickAddCalendar", state.quickAddCalendar); err != nil { fmt.Println("saveAccountState:quickAddCalendar error:", err) } } // loadAccountState loads all of the config into the state struct func loadAccountState() { var err error var calListJson []byte calListJson = state.cfg.GetBytes("calendarList") if err = json.Unmarshal(calListJson, &state.account.CalendarList); err == nil { if len(state.account.CalendarList) > 0 { if err != nil { fmt.Println("error: ", err) } if state.account.CalListUseBy, err = state.cfg.GetDateTime("calListUseBy"); err != nil { fmt.Println("error: ", err) } } } else { fmt.Println("error: ", err) } var evListJson []byte evListJson = state.cfg.GetBytes("eventList") if err = json.Unmarshal(evListJson, &state.account.EventList); err == nil { if len(state.account.EventList) > 0 { if err != nil { fmt.Println("error: ", err) } if state.account.EventListUseBy, err = state.cfg.GetDateTime("eventListUseBy"); err != nil { fmt.Println("error: ", err) } } } else { fmt.Println("error: ", err) } // If the 'defaultCalendars' cfg is set to 'primary' (or not at all) // we need to actually but the primary cal id in there var defCal []string defCal, err = state.cfg.GetArray("defaultCalendars") if len(defCal) == 0 || (len(defCal) == 1 && defCal[0] == "primary") { gCal, err := state.account.Service.CalendarList.Get("primary").Do() if err == nil { defCal = []string{gCal.Id} } } state.defaultCalendars = defCal // Verify/Set QuickAdd Calendar state.quickAddCalendar = state.cfg.Get("quickAddCalendar") if state.quickAddCalendar == "" { gCal, err := state.account.Service.CalendarList.Get("primary").Do() if err == nil { state.quickAddCalendar = gCal.Id } } }