From 727a3fdf85e5c29e3e6d131d43bb27bb8d40e4dc Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Mon, 18 Dec 2017 15:38:16 -0500 Subject: [PATCH] Moving wherewhen elsewhere --- wherewhen/.gitignore | 2 - wherewhen/Makefile | 2 - wherewhen/google_calendar.go | 77 --------- wherewhen/main.go | 308 ----------------------------------- 4 files changed, 389 deletions(-) delete mode 100644 wherewhen/.gitignore delete mode 100644 wherewhen/Makefile delete mode 100644 wherewhen/google_calendar.go delete mode 100644 wherewhen/main.go diff --git a/wherewhen/.gitignore b/wherewhen/.gitignore deleted file mode 100644 index c81cdbe..0000000 --- a/wherewhen/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -client_secret.json -/wherewhen diff --git a/wherewhen/Makefile b/wherewhen/Makefile deleted file mode 100644 index f5fdd25..0000000 --- a/wherewhen/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -wherewhen: $(shell git ls-files '*.go') - go build -x diff --git a/wherewhen/google_calendar.go b/wherewhen/google_calendar.go deleted file mode 100644 index c006708..0000000 --- a/wherewhen/google_calendar.go +++ /dev/null @@ -1,77 +0,0 @@ -package main - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "net/url" - "os" - "os/user" - "path/filepath" - - "github.com/sirupsen/logrus" - "golang.org/x/oauth2" -) - -func getClient(ctx context.Context, config *oauth2.Config) *http.Client { - cacheFile, err := tokenCacheFile() - if err != nil { - logrus.Fatalf("Unable to get path to cached credential file. %v", err) - } - tok, err := tokenFromFile(cacheFile) - if err != nil { - tok = getTokenFromWeb(config) - saveToken(cacheFile, tok) - } - return config.Client(ctx, tok) -} - -func getTokenFromWeb(config *oauth2.Config) *oauth2.Token { - authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline) - fmt.Printf("Go to the following link in your browser then type the "+ - "authorization code: \n%v\n", authURL) - - var code string - if _, err := fmt.Scan(&code); err != nil { - logrus.Fatalf("Unable to read authorization code %v", err) - } - - tok, err := config.Exchange(oauth2.NoContext, code) - if err != nil { - logrus.Fatalf("Unable to retrieve token from web %v", err) - } - return tok -} - -func tokenCacheFile() (string, error) { - usr, err := user.Current() - if err != nil { - return "", err - } - tokenCacheDir := filepath.Join(usr.HomeDir, ".credentials") - os.MkdirAll(tokenCacheDir, 0700) - return filepath.Join(tokenCacheDir, - url.QueryEscape("wherewhen.json")), err -} - -func tokenFromFile(file string) (*oauth2.Token, error) { - f, err := os.Open(file) - if err != nil { - return nil, err - } - t := &oauth2.Token{} - err = json.NewDecoder(f).Decode(t) - defer f.Close() - return t, err -} - -func saveToken(file string, token *oauth2.Token) { - fmt.Printf("Saving credential file to: %s\n", file) - f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) - if err != nil { - logrus.Fatalf("Unable to cache oauth token: %v", err) - } - defer f.Close() - json.NewEncoder(f).Encode(token) -} diff --git a/wherewhen/main.go b/wherewhen/main.go deleted file mode 100644 index 0bee59d..0000000 --- a/wherewhen/main.go +++ /dev/null @@ -1,308 +0,0 @@ -package main - -import ( - "encoding/json" - "flag" - "fmt" - "io/ioutil" - "strconv" - "strings" - "syscall" - "time" - - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - "golang.org/x/oauth2/google" - "google.golang.org/api/calendar/v3" -) - -var ( - nowTime = time.Now() - oneYearString = fmt.Sprintf("%dh", 365*24) - oneYear, _ = time.ParseDuration(oneYearString) - clientSecretFlag = flag.String( - "s", getEnvDefault("CLIENT_SECRET", "client_secret.json"), "client secret json file") - calendarIDFlag = flag.String( - "i", getEnvDefault("CALENDAR", "primary"), "calendar ID to search") - endTimeFlag = flag.String( - "e", getEnvDefault("END_TIME", nowTime.Format(ymdFmt)), "end time for search") - timeWindowFlag = flag.Duration( - "t", func() time.Duration { - stringVal := getEnvDefault("DURATION", oneYearString) - val, _ := time.ParseDuration(stringVal) - return val - }(), "time window duration from before end time") - defaultLocationFlag = flag.String( - "l", getEnvDefault("DEFAULT_LOCATION", "notset"), "default location for where") - locationAliasesFlag = flag.String( - "a", getEnvDefault("LOCATION_ALIASES", ""), "location alias key:value mappings") - verboseFlag = flag.Bool("v", func() bool { - stringVal := getEnvDefault("VERBOSE", "no") - val, _ := strconv.ParseBool(stringVal) - return val - }(), "enable verbose-er output") -) - -const ( - ymdFmt = "2006-01-02" -) - -func getEnvDefault(key, defVal string) string { - for _, k := range []string{"WHEREWHEN_" + key, key} { - if v, ok := syscall.Getenv(k); ok { - return v - } - } - return defVal -} - -type lilEvent struct { - Start string `json:"start"` - End string `json:"end"` - Location string `json:"loc"` - Summary string `json:"summ"` -} - -func (e *lilEvent) HasDate(d string) bool { - if e.Start == d { - logrus.Debugf("match for %s at %s", d, e.Start) - return true - } - - dT, err := time.Parse(ymdFmt, d) - if err != nil { - logrus.Error(err) - return false - } - - dr := e.dateRange() - return dr[0].Before(dT) && dr[1].After(dT) -} - -func (e *lilEvent) dateRange() []time.Time { - ret := []time.Time{} - for _, t := range []string{e.Start, e.End} { - parsedDate, err := time.Parse(ymdFmt, t) - if err != nil { - logrus.Error(err) - ret = append(ret, time.Time{}) - continue - } - ret = append(ret, parsedDate) - } - - return ret -} - -type lilDay struct { - Date string `json:"date"` - Location string `json:"loc"` -} - -func generateDays(startT, endT time.Time) []*lilDay { - defaultLocation := *defaultLocationFlag - days := []*lilDay{} - - curT := startT - for { - if curT.After(endT) { - return days - } - - days = append(days, &lilDay{ - Date: curT.Format(ymdFmt), - Location: defaultLocation, - }) - - curT = curT.Add(24 * time.Hour) - } -} - -type lilStats struct { - Locs map[string]int `json:"locs"` - LocsPercentage map[string]float64 `json:"locs_pct"` - TotalDays int `json:"total_days"` - StartDate string `json:"start_date"` - EndDate string `json:"end_date"` -} - -func main() { - flag.Parse() - if *verboseFlag { - logrus.SetLevel(logrus.DebugLevel) - } - - ctx := context.Background() - - b, err := ioutil.ReadFile(*clientSecretFlag) - if err != nil { - logrus.Fatalf("Unable to read client secret file: %v", err) - } - - config, err := google.ConfigFromJSON(b, calendar.CalendarReadonlyScope) - if err != nil { - logrus.Fatalf("Unable to parse client secret file to config: %v", err) - } - client := getClient(ctx, config) - - srv, err := calendar.New(client) - if err != nil { - logrus.Fatalf("Unable to retrieve calendar Client %v", err) - } - - endT, err := time.Parse(ymdFmt, *endTimeFlag) - if err != nil { - logrus.Fatalf("Unable to parse end time %q: %v", *endTimeFlag, err) - } - - maxResults := int64(2500) - startT := endT.Add(-*timeWindowFlag) - t := startT.Format(time.RFC3339) - events, err := srv.Events.List(*calendarIDFlag).ShowDeleted(false). - SingleEvents(true).TimeMin(t).TimeMax(endT.Format(time.RFC3339)). - MaxResults(maxResults).OrderBy("startTime").Do() - if err != nil { - logrus.Fatalf("Unable to retrieve next %d events. %v", maxResults, err) - } - - logrus.WithField("count", len(events.Items)).Debugf("found events") - logrus.Debugf("generating days between %v and %v", startT, endT) - - days := generateDays(startT, endT) - if len(days) <= 0 { - logrus.WithFields(logrus.Fields{ - "start_time": startT, - "end_time": endT, - }).Fatal("no days generated") - } - - foundEvents := []*lilEvent{} - defaultLocation := *defaultLocationFlag - - logrus.Debugf("generated %d days between %v and %v", len(days), startT, endT) - - locationAliases := map[string]string{} - for _, str := range strings.Split(*locationAliasesFlag, ",") { - strParts := strings.SplitN(strings.ToLower(strings.TrimSpace(str)), ":", 2) - if len(strParts) < 2 { - logrus.WithField("parts", strParts).Warnf("unexpected location alias mapping length") - continue - } - - locationAliases[strParts[0]] = strParts[1] - } - - logrus.WithField("location_aliases", locationAliases).Debug("parsed location aliases") - - if len(events.Items) > 0 { - for _, i := range events.Items { - var ( - startDate string - endDate string - ) - - if i.Start.DateTime != "" { - startT, err := time.Parse(time.RFC3339, i.Start.DateTime) - if err != nil { - logrus.Errorf("error parsing start date: %v", err) - continue - } - - endT, err := time.Parse(time.RFC3339, i.End.DateTime) - if err != nil { - logrus.Errorf("error parsing end date: %v", err) - continue - } - startDate = startT.Format(ymdFmt) - endDate = endT.Format(ymdFmt) - } else { - startDate = i.Start.Date - endDate = i.End.Date - } - - evt := &lilEvent{ - Start: startDate, - End: endDate, - Location: defaultLocation, - Summary: strings.ToLower(strings.TrimSpace(i.Summary)), - } - - summ := strings.ToLower(i.Summary) - if strings.Contains(summ, "possible") { - continue - } - - parts := strings.Split(summ, " ") - locIdx := 0 - for i, part := range parts { - if part == "in" || part == "with" { - locIdx = i + 1 - } - } - loc := strings.TrimSpace(parts[locIdx]) - if locAlias, ok := locationAliases[loc]; ok { - loc = locAlias - } - evt.Location = loc - - if evt.Start == evt.End { - logrus.Debugf("skipping same-day event on %s (%s)", evt.Start, evt.Summary) - continue - } - foundEvents = append(foundEvents, evt) - } - } else { - logrus.Info("No events found") - } - - for _, day := range days { - logrus.Debugf("working on date %v", day) - - for _, evt := range foundEvents { - logrus.Debugf("checking if %s is in range %s %s", day.Date, evt.Start, evt.End) - - if evt.HasDate(day.Date) { - logrus.Debugf("match found for %s in range %s %s, setting location to %s", day.Date, evt.Start, evt.End, evt.Location) - day.Location = evt.Location - } - } - } - - stats := &lilStats{ - Locs: map[string]int{}, - LocsPercentage: map[string]float64{}, - TotalDays: len(days), - StartDate: days[0].Date, - EndDate: days[len(days)-1].Date, - } - - for _, day := range days { - if _, ok := stats.Locs[day.Location]; !ok { - stats.Locs[day.Location] = 0 - } - - stats.Locs[day.Location]++ - - if !*verboseFlag { - continue - } - - asJson, err := json.Marshal(day) - if err != nil { - logrus.Error(err) - continue - } - - fmt.Println(string(asJson)) - } - - for loc, count := range stats.Locs { - stats.LocsPercentage[loc] = float64(count) / float64(len(days)) - } - - statsJson, err := json.Marshal(map[string]*lilStats{"stats": stats}) - if err != nil { - logrus.Fatal(err) - } - fmt.Println(string(statsJson)) -}