From 3ce83f327abeb45a3df135600f7364c52884b8f6 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Wed, 9 Sep 2020 03:26:23 +0000 Subject: [PATCH] Initial commit --- .gitignore | 2 + auth.go | 74 ++++++++++++++++++++++ main.go | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 256 insertions(+) create mode 100644 .gitignore create mode 100644 auth.go create mode 100644 main.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..56f9084 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +credentials.json +token.json diff --git a/auth.go b/auth.go new file mode 100644 index 0000000..492188d --- /dev/null +++ b/auth.go @@ -0,0 +1,74 @@ +package main + +import ( + "encoding/json" + "fmt" + "log" + "net/http" + "os" + + "golang.org/x/net/context" + "golang.org/x/oauth2" +) + +// Retrieve a token, saves the token, then returns the generated client. +func getClient(config *oauth2.Config) (*http.Client, error) { + // The file token.json stores the user's access and refresh tokens, and is + // created automatically when the authorization flow completes for the first + // time. + tokFile := "token.json" + tok, err := tokenFromFile(tokFile) + if err != nil { + tok, err = getTokenFromWeb(config) + if err != nil { + return nil, err + } + + err = saveToken(tokFile, tok) + if err != nil { + return nil, err + } + } + return config.Client(context.Background(), tok), nil +} + +// Request a token from the web, then returns the retrieved token. +func getTokenFromWeb(config *oauth2.Config) (*oauth2.Token, error) { + authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline) + log.Printf("Go to the following link in your browser then type the authorization code: \n%v", authURL) + + var authCode string + if _, err := fmt.Scan(&authCode); err != nil { + return nil, err + } + + tok, err := config.Exchange(context.TODO(), authCode) + if err != nil { + return nil, err + } + return tok, nil +} + +// Retrieves a token from a local file. +func tokenFromFile(file string) (*oauth2.Token, error) { + f, err := os.Open(file) + if err != nil { + return nil, err + } + defer f.Close() + tok := &oauth2.Token{} + err = json.NewDecoder(f).Decode(tok) + return tok, err +} + +// Saves a token to a file path. +func saveToken(path string, token *oauth2.Token) error { + f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) + if err != nil { + return err + } + defer f.Close() + json.NewEncoder(f).Encode(token) + + return nil +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..54153cf --- /dev/null +++ b/main.go @@ -0,0 +1,180 @@ +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "log" + "time" + + "golang.org/x/oauth2/google" + "google.golang.org/api/calendar/v3" +) + +var calName = flag.String("calendar", "", "name of calendar") + +var students = []string{ + "oliver.park@heliosns.org", +} + +var classes = []Class { + Class{ + Summary: "Test 2", + Start: "22:00", + End: "22:30", + Days: []time.Weekday{time.Monday, time.Tuesday, time.Wednesday, time.Thursday}, + Zoom: "https://us02web.zoom.us/j/2274643506?pwd=Nm5NUXMwOVJKbEUzNE5VSkZCQzJ2UT09", + }, +} + +type Class struct { + Summary string + Start string + End string + Students []string + Days []time.Weekday + Zoom string +} + +func main() { + flag.Parse() + + b, err := ioutil.ReadFile("credentials.json") + if err != nil { + log.Fatal(err) + } + + // If modifying these scopes, delete your previously saved token.json. + config, err := google.ConfigFromJSON(b, calendar.CalendarScope) + if err != nil { + log.Fatal(err) + } + client, err := getClient(config) + if err != nil { + log.Fatal(err) + } + + srv, err := calendar.New(client) + if err != nil { + log.Fatal(err) + } + + calendars, err := srv.CalendarList.List().Do() + if err != nil { + log.Fatal(err) + } + var myCal *calendar.CalendarListEntry + for _, item := range calendars.Items { + if item.Summary == *calName { + myCal = item + break + } + } + if myCal == nil { + log.Fatalf("calendar '%s' not found", *calName) + } + + loc, err := time.LoadLocation("US/Pacific") + if err != nil { + log.Fatal(err) + } + + now := time.Now().In(loc) + + dateStr := now.Format("2006-01-02") + + // TOOD: loop through days + + for _, class := range classes { + found := false + for _, day := range class.Days { + if day == now.Weekday() { + found = true + break + } + } + if !found { + continue + } + + ev := &calendar.Event{ + Summary: class.Summary, + Start: &calendar.EventDateTime{ + DateTime: fmt.Sprintf("%sT%s:00", dateStr, class.Start), + TimeZone: "US/Pacific", + }, + End: &calendar.EventDateTime{ + DateTime: fmt.Sprintf("%sT%s:00", dateStr, class.End), + TimeZone: "US/Pacific", + }, + Attendees: []*calendar.EventAttendee{}, + } + + attendees := class.Students + if len(attendees) == 0 { + attendees = students + } + + for _, student := range attendees { + ev.Attendees = append( + ev.Attendees, + &calendar.EventAttendee{ + Email: student, + }, + ) + } + + if class.Zoom != "" { + ev.Description = fmt.Sprintf(`Zoom: %s`, class.Zoom) + } + + _, err := srv.Events.Insert(myCal.Id, ev).Do() + if err != nil { + log.Fatal(err) + } + } + + + /* + ev := &calendar.Event{ + Summary: "Test event", + Start: &calendar.EventDateTime{ + DateTime: "2020-09-09T16:00:00", + TimeZone: "US/Pacific", + }, + End: &calendar.EventDateTime{ + DateTime: "2020-09-09T17:00:00", + TimeZone: "US/Pacific", + }, + Attendees: []*calendar.EventAttendee{ + &calendar.EventAttendee{ + Email: "oliver.park@heliosns.org", + }, + }, + } + + res, err := srv.Events.Insert(myCal.Id, ev).Do() + if err != nil { + log.Fatal(err) + } + + log.Printf("%#v", res) + */ + + /* + t := time.Now().Format(time.RFC3339) + events, err := srv.Events.List(myCal.Id).ShowDeleted(false). + SingleEvents(true).TimeMin(t).MaxResults(250).OrderBy("startTime").Do() + if err != nil { + log.Fatal(err) + } + + for _, item := range events.Items { + date := item.Start.DateTime + if date == "" { + date = item.Start.Date + } + log.Printf("%v (%v)", item.Summary, date) + } + */ +}