gal/struct_account.go

210 lines
4.6 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
ActiveCalendars []string
QuickAddCal string
Colors *calendar.Colors
}
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())
}
a.Colors, err = calendar.NewColorsService(a.Service).Get().Do()
return a, err
}
// 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) GetTodaysActiveEvents() []Event {
allEvents := a.GetTodaysEvents()
var ret []Event
var startIdx int
for i := range allEvents {
for _, calId := range a.ActiveCalendars {
if allEvents[i].CalendarId == calId {
if time.Until(allEvents[i].GetStartTime()) <= 0 {
startIdx--
}
ret = append(ret, allEvents[i])
break
}
}
}
sort.Sort(ByStartTime(ret))
for i := range ret {
ret[i].InstanceId = startIdx
startIdx++
}
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
}
func (a *Account) GetCalendarById(id string) (*Calendar, error) {
calList := a.GetCalendarList()
for _, c := range calList {
if c.Id == id {
return &c, nil
}
}
return nil, errors.New("Couldn't find calendar")
}
func (a *Account) GetCalendarColor(id string) (*calendar.ColorDefinition, error) {
var cal *Calendar
var err error
if cal, err = a.GetCalendarById(id); err != nil {
return nil, err
}
if c, ok := a.Colors.Calendar[cal.ColorId]; ok {
return &c, nil
}
return nil, errors.New("Error Finding Calendar Color")
}
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
}