package main import ( "encoding/json" "fmt" "io/ioutil" "log" "os" "sort" "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() // TODO: Get calendars flagged as default list := state.account.GetCalendarList() var todayEvents []Event if len(list) > 0 { for defIdx := range state.defaultCalendars { for i := range list { if list[i].Deleted { // Deleted calendar, next please continue } if state.defaultCalendars[defIdx] == list[i].Id { todayEvents = append(todayEvents, list[i].GetTodaysEvents()...) } } } sort.Sort(ByStartTime(todayEvents)) for _, e := range todayEvents { if e.GetStartTimeString() == "00:00:00" { color.New(color.FgGreen).Println("[All Day ] " + e.Summary) } else { if time.Until(e.GetStartTime()) < time.Hour { color.New(color.FgYellow).Add(color.Bold).Println("[" + e.GetStartTimeString() + "] " + e.Summary) } else if time.Until(e.GetStartTime()) < time.Minute*30 { color.New(color.FgRed).Add(color.Bold).Println("[" + e.GetStartTimeString() + "] " + e.Summary) } else { fmt.Println("[" + e.GetStartTimeString() + "] " + e.Summary) } } } } else { fmt.Printf("No calendars found.\n") } case "config": // Open the Configuration CUI screen InitComm() DoConfig() case "defaults": // Show Defaults InitComm() 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) } } 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) } // 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 } } }