gal/struct_account.go

160 lines
3.5 KiB
Go

package main
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"log"
"net/http"
"sort"
"time"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
calendar "google.golang.org/api/calendar/v3"
)
type Account struct {
CC *CalClient
Service *calendar.Service
CalendarList []Calendar
CalListUseBy time.Time
EventList []Event // Today's Events
EventListUseBy time.Time
}
func GetAccount(secret, token []byte) (*Account, error) {
var err error
a := new(Account)
// Create the CalClient
a.CC = CreateClient(secret, token)
a.CC.TokenToRaw()
// Create the Calendar Service
a.Service, err = calendar.New(a.CC.client)
if err != nil {
return nil, errors.New("Unable to retrieve calendar Client: " + err.Error())
}
return a, nil
}
// Get Todays Events gets events for today from all calendars
func (a *Account) GetTodaysEvents() []Event {
if time.Now().Before(a.EventListUseBy) {
return a.EventList
}
var ret []Event
list := a.GetCalendarList()
for i := range list {
if list[i].Deleted {
continue
}
ret = append(ret, list[i].GetTodaysEvents()...)
}
sort.Sort(ByStartTime(ret))
a.EventList = ret
a.EventListUseBy = time.Now().Add(time.Hour * 6)
return ret
}
func (a *Account) GetDefaultCalendar() *Calendar {
c, _ := a.Service.CalendarList.Get("primary").Do()
return GoogleCalendarToLocal(c)
}
func (a *Account) GetCalendarList() []Calendar {
if time.Now().Before(a.CalListUseBy) {
return a.CalendarList
}
var ret []Calendar
calList, err := a.Service.CalendarList.List().Do()
if err != nil {
return ret
}
for _, c := range calList.Items {
ret = append(ret, *GoogleCalendarToLocal(c))
}
a.CalendarList = ret
a.CalListUseBy = time.Now().Add(time.Hour * 24 * 7)
return ret
}
type CalClient struct {
rawClientSecret []byte
rawToken []byte
ctx context.Context
cfg *oauth2.Config
tkn *oauth2.Token
client *http.Client
}
func CreateClient(secret, tkn []byte) *CalClient {
var err error
c := CalClient{
rawClientSecret: []byte(secret),
rawToken: []byte(tkn),
}
c.ctx = context.Background()
c.cfg, err = google.ConfigFromJSON(c.rawClientSecret, calendar.CalendarScope)
if err != nil {
log.Fatalf("unable to parse client secret file to config: %v", err)
}
// Try to create the client with the passed token
c.client, err = c.GetClient()
if err != nil {
log.Fatalf("unable to create client: %v", err)
}
return &c
}
func (c *CalClient) GetClient() (*http.Client, error) {
err := c.tokenFromRaw()
if err != nil {
err = c.tokenFromWeb()
if err != nil {
return nil, err
}
}
return c.cfg.Client(c.ctx, c.tkn), nil
}
func (c *CalClient) tokenFromRaw() error {
c.tkn = &oauth2.Token{}
tmpToken := bytes.NewBuffer(c.rawToken)
err := json.NewDecoder(tmpToken).Decode(c.tkn)
return err
}
func (c *CalClient) tokenFromWeb() error {
var err error
authURL := c.cfg.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 {
log.Fatalf("Unable to read authorization code %v", err)
}
if c.tkn, err = c.cfg.Exchange(oauth2.NoContext, code); err == nil {
c.TokenToRaw()
}
return err
}
func (c *CalClient) TokenToRaw() {
var tmpToken bytes.Buffer
t := c.tkn
json.NewEncoder(&tmpToken).Encode(t)
c.rawToken = tmpToken.Bytes()
}
func (c *CalClient) GetRawToken() []byte {
return c.rawToken
}