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

Added gspreadsheets module

This commit is contained in:
Andrew_Zol 2018-06-08 20:27:39 +03:00
parent e551a2530c
commit f2b943e3d6
4 changed files with 204 additions and 0 deletions

1
.gitignore vendored
View File

@ -15,6 +15,7 @@
# Misc
.DS_Store
gcal/client_secret.json
gspreadsheets/client_secret.json
#intellij idea
.idea/

145
gspreadsheets/client.go Normal file
View File

@ -0,0 +1,145 @@
/*
* This butt-ugly code is direct from Google itself
* https://developers.google.com/sheets/api/quickstart/go
*/
package gspreadsheets
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
"os/user"
"path/filepath"
"strings"
"github.com/senorprogrammer/wtf/wtf"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
sheets "google.golang.org/api/sheets/v4"
)
/* -------------------- Exported Functions -------------------- */
func Fetch() ([]*sheets.ValueRange, error) {
ctx := context.Background()
secretPath, _ := wtf.ExpandHomeDir(Config.UString("wtf.mods.gspreadsheets.secretFile"))
b, err := ioutil.ReadFile(secretPath)
if err != nil {
log.Fatalf("Unable to read secretPath. %v", err)
return nil, err
}
config, err := google.ConfigFromJSON(b, "https://www.googleapis.com/auth/spreadsheets.readonly")
if err != nil {
log.Fatalf("Unable to get config from JSON. %v", err)
return nil, err
}
client := getClient(ctx, config)
srv, err := sheets.New(client)
if err != nil {
log.Fatalf("Unable to get create server. %v", err)
return nil, err
}
cells := wtf.ToStrs(Config.UList("wtf.mods.gspreadsheets.cells.addresses"))
documentId := Config.UString("wtf.mods.gspreadsheets.sheetId")
addresses := strings.Join(cells[:], ";")
responses := make([]*sheets.ValueRange, len(cells))
for i := 0; i < len(cells); i++ {
resp, err := srv.Spreadsheets.Values.Get(documentId, cells[i]).Do()
if err != nil {
log.Fatalf("Error fetching cells %s", addresses)
return nil, err
}
responses[i] = resp
}
return responses, err
}
/* -------------------- Unexported Functions -------------------- */
// 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("spreadsheets-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)
}

56
gspreadsheets/widget.go Normal file
View File

@ -0,0 +1,56 @@
package gspreadsheets
import (
"fmt"
"github.com/senorprogrammer/wtf/wtf"
"github.com/olebedev/config"
sheets "google.golang.org/api/sheets/v4"
)
// Config is a pointer to the global config object
var Config *config.Config
type Widget struct {
wtf.TextWidget
}
func NewWidget() *Widget {
widget := Widget{
TextWidget: wtf.NewTextWidget(" Google Spreadsheets ", "gspreadsheets", false),
}
return &widget
}
/* -------------------- Exported Functions -------------------- */
func (widget *Widget) Refresh() {
if widget.Disabled() {
return
}
cells, _ := Fetch()
widget.UpdateRefreshedAt()
widget.View.SetText(fmt.Sprintf("%s", widget.contentFrom(cells)))
}
/* -------------------- Unexported Functions -------------------- */
func (widget *Widget) contentFrom(valueRanges []*sheets.ValueRange) string {
if valueRanges == nil {
return "error 1"
}
valuesColor := Config.UString("wtf.mods.gspreadsheets.colors.values", "green")
res := ""
cells := wtf.ToStrs(Config.UList("wtf.mods.gspreadsheets.cells.names"))
for i := 0; i < len(valueRanges); i++ {
res = res + fmt.Sprintf("%s\t[%s]%s\n", cells[i], valuesColor, valueRanges[i].Values[0][0])
}
return res
}

2
wtf.go
View File

@ -16,6 +16,7 @@ import (
"github.com/senorprogrammer/wtf/cryptoexchanges/bittrex"
"github.com/senorprogrammer/wtf/cryptoexchanges/cryptolive"
"github.com/senorprogrammer/wtf/gcal"
"github.com/senorprogrammer/wtf/gspreadsheets"
"github.com/senorprogrammer/wtf/git"
"github.com/senorprogrammer/wtf/github"
"github.com/senorprogrammer/wtf/help"
@ -220,6 +221,7 @@ func makeWidgets(app *tview.Application, pages *tview.Pages) {
cmdrunner.Config = Config
cryptolive.Config = Config
gcal.Config = Config
gspreadsheets.Config = Config
git.Config = Config
github.Config = Config
ipinfo.Config = Config