1
0
mirror of https://github.com/taigrr/wtf synced 2025-01-18 04:03:14 -08:00

Adds in Google Calendar and Weather support (hard-coded right now)

This commit is contained in:
Chris Cummer 2018-03-28 19:40:20 -07:00 committed by Chris Cummer
parent 176052c78f
commit 8946e5cf24
12 changed files with 301 additions and 27 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
DS_Store
gcal/client_secret.json

26
bamboohr/widget.go Normal file
View File

@ -0,0 +1,26 @@
package bamboohr
import (
"fmt"
"github.com/rivo/tview"
)
func Widget() tview.Primitive {
items := Fetch()
widget := tview.NewTextView()
widget.SetBorder(true)
widget.SetDynamicColors(true)
widget.SetTitle(" 🐨 Away ")
data := ""
for _, item := range items {
str := fmt.Sprintf(" [green]%s[white]\n %s - %s\n\n", item.Name(), item.PrettyStart(), item.PrettyEnd())
data = data + str
}
fmt.Fprintf(widget, "%s", data)
return widget
}

BIN
gcal/.DS_Store vendored Normal file

Binary file not shown.

125
gcal/client.go Normal file
View File

@ -0,0 +1,125 @@
/*
* This butt-ugly code is direct from Google itself
* https://developers.google.com/calendar/quickstart/go
*/
package gcal
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
"os/user"
"path/filepath"
"time"
"golang.org/x/net/context"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/calendar/v3"
)
// getClient uses a Context and Config to retrieve a Token
// then generate a Client. It returns the generated Client.
func getClient(ctx context.Context, config *oauth2.Config) *http.Client {
cacheFile, err := tokenCacheFile()
if err != nil {
log.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)
}
// getTokenFromWeb uses Config to request a Token.
// It returns the retrieved Token.
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 {
log.Fatalf("Unable to read authorization code %v", err)
}
tok, err := config.Exchange(oauth2.NoContext, code)
if err != nil {
log.Fatalf("Unable to retrieve token from web %v", err)
}
return tok
}
// tokenCacheFile generates credential file path/filename.
// It returns the generated credential path/filename.
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("calendar-go-quickstart.json")), err
}
// tokenFromFile retrieves a Token from a given file path.
// It returns the retrieved Token and any read error encountered.
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
}
// saveToken uses a file path to create a file and store the
// token in it.
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 {
log.Fatalf("Unable to cache oauth token: %v", err)
}
defer f.Close()
json.NewEncoder(f).Encode(token)
}
func Fetch() *calendar.Events {
ctx := context.Background()
b, err := ioutil.ReadFile("./gcal/client_secret.json")
if err != nil {
log.Fatalf("Unable to read client secret file: %v", err)
}
config, err := google.ConfigFromJSON(b, calendar.CalendarReadonlyScope)
if err != nil {
log.Fatalf("Unable to parse client secret file to config: %v", err)
}
client := getClient(ctx, config)
srv, err := calendar.New(client)
if err != nil {
log.Fatalf("Unable to retrieve calendar Client %v", err)
}
t := time.Now().Format(time.RFC3339)
events, err := srv.Events.List("primary").ShowDeleted(false).
SingleEvents(true).TimeMin(t).MaxResults(10).OrderBy("startTime").Do()
if err != nil {
log.Fatalf("Unable to retrieve next ten of the user's events. %v", err)
}
return events
}

35
gcal/widget.go Normal file
View File

@ -0,0 +1,35 @@
package gcal
import (
"fmt"
"time"
"github.com/rivo/tview"
)
func Widget() tview.Primitive {
events := Fetch()
widget := tview.NewTextView()
widget.SetBorder(true)
widget.SetDynamicColors(true)
widget.SetTitle(" 🐸 Calendar ")
data := ""
for _, item := range events.Items {
ts, _ := time.Parse(time.RFC3339, item.Start.DateTime)
timestamp := ts.Format("Mon Jan _2 15:04:05 2006")
color := "red"
if ts.Before(time.Now()) {
color = "grey"
}
str := fmt.Sprintf(" [%s]%s[white]\n %s\n\n", color, item.Summary, timestamp)
data = data + str
}
fmt.Fprintf(widget, "%s", data)
return widget
}

11
github/client.go Normal file
View File

@ -0,0 +1,11 @@
package github
import (
_ "github.com/google/go-github/github"
)
func Fetch() string {
//client := github.NewClient(nil)
return ""
}

View File

@ -1,3 +0,0 @@
package wtfgithub
import ()

18
github/widget.go Normal file
View File

@ -0,0 +1,18 @@
package github
import (
"fmt"
"github.com/rivo/tview"
)
func Widget() tview.Primitive {
widget := tview.NewTextView()
widget.SetBorder(true)
widget.SetDynamicColors(true)
widget.SetTitle(" 🐱 Github ")
fmt.Fprintf(widget, "%s", "This is github")
return widget
}

18
status/widget.go Normal file
View File

@ -0,0 +1,18 @@
package status
import (
"fmt"
"github.com/rivo/tview"
)
func Widget() tview.Primitive {
widget := tview.NewTextView()
widget.SetBorder(true)
widget.SetDynamicColors(true)
widget.SetTitle(" 🦊 Status ")
fmt.Fprintf(widget, "%s", "cats and gods\ndogs and tacs")
return widget
}

19
weather/client.go Normal file
View File

@ -0,0 +1,19 @@
package weather
import (
"os"
owm "github.com/briandowns/openweathermap"
)
func Fetch() *owm.CurrentWeatherData {
w, err := owm.NewCurrent("C", "EN", os.Getenv("WTF_OWM_API_KEY"))
if err != nil {
panic(err)
}
//w.CurrentByName("Toronto,ON")
w.CurrentByID(6173331)
return w
}

38
weather/widget.go Normal file
View File

@ -0,0 +1,38 @@
package weather
import (
"bytes"
"fmt"
"text/template"
"github.com/rivo/tview"
)
const weatherTemplate = `
{{range .Weather}}{{.Description}}{{end}}
Current: {{.Main.Temp}}° C
High: {{.Main.TempMax}}° C
Low: {{.Main.TempMin}}° C
`
func Widget() tview.Primitive {
data := Fetch()
widget := tview.NewTextView()
widget.SetBorder(true)
widget.SetDynamicColors(true)
widget.SetTitle(fmt.Sprintf(" 🌤 Weather - %s ", data.Name))
//fmt.Fprintf(widget, " %s", data.Name)
var tpl bytes.Buffer
tmpl, _ := template.New("weather").Parse(weatherTemplate)
if err := tmpl.Execute(&tpl, data); err != nil {
panic(err)
}
fmt.Fprintf(widget, " %s ", tpl.String())
return widget
}

33
wtf.go
View File

@ -1,42 +1,27 @@
package main
import (
"fmt"
"github.com/rivo/tview"
"github.com/senorprogrammer/wtf/bamboohr"
"github.com/senorprogrammer/wtf/gcal"
"github.com/senorprogrammer/wtf/status"
"github.com/senorprogrammer/wtf/weather"
)
func main() {
app := tview.NewApplication()
grid := tview.NewGrid()
grid.SetRows(10, 40) // 10 high, 40 high
grid.SetColumns(40, 40) // 40 wide, 40 wide
grid.SetRows(10, 40, 30) // How _high_ the row is, in terminal rows
grid.SetColumns(40, 40) // How _wide_ the column is, in terminal columns
grid.SetBorder(false)
grid.AddItem(bambooView(), 0, 0, 1, 1, 0, 0, false)
grid.AddItem(bamboohr.Widget(), 0, 0, 1, 1, 0, 0, false)
grid.AddItem(gcal.Widget(), 1, 0, 1, 1, 0, 0, false)
grid.AddItem(status.Widget(), 2, 0, 2, 3, 0, 0, false)
grid.AddItem(weather.Widget(), 0, 1, 1, 1, 0, 0, false)
if err := app.SetRoot(grid, true).Run(); err != nil {
panic(err)
}
}
func bambooView() tview.Primitive {
items := bamboohr.Fetch()
bamboo := tview.NewTextView()
bamboo.SetBorder(true)
bamboo.SetDynamicColors(true)
bamboo.SetTitle(" 🐨 Away ")
data := ""
for _, item := range items {
str := fmt.Sprintf("[green]%s[white]\n%s - %s\n\n", item.Name(), item.PrettyStart(), item.PrettyEnd())
data = data + str
}
fmt.Fprintf(bamboo, "%s", data)
return bamboo
}