Files
heliosian/internal/data/sheet.go
T

78 lines
1.7 KiB
Go

package data
import (
"context"
"fmt"
"path/filepath"
"strings"
"google.golang.org/api/option"
"google.golang.org/api/sheets/v4"
)
type Sheet struct {
service *sheets.Service
spreadsheets map[string]string
}
func KeyFile() (string, error) {
matches, err := filepath.Glob("creds/*.json")
if err != nil {
return "", err
}
if len(matches) == 0 {
return "", fmt.Errorf("no service account key found in creds/")
}
return matches[0], nil
}
func NewSheet(keyFile string, spreadsheets map[string]string) (*Sheet, error) {
service, err := sheets.NewService(context.Background(),
option.WithCredentialsFile(keyFile),
option.WithScopes(sheets.SpreadsheetsReadonlyScope))
if err != nil {
return nil, err
}
return &Sheet{service: service, spreadsheets: spreadsheets}, nil
}
func (s *Sheet) Table(app, name string) ([]map[string]string, error) {
id, ok := s.spreadsheets[app]
if !ok {
return nil, fmt.Errorf("no spreadsheet configured for app %q", app)
}
resp, err := s.service.Spreadsheets.Values.Get(id, "'"+strings.ReplaceAll(name, "'", "''")+"'").Do()
if err != nil {
return nil, err
}
return toRecords(resp.Values), nil
}
func toRecords(values [][]interface{}) []map[string]string {
if len(values) == 0 {
return nil
}
header := make([]string, len(values[0]))
for i, cell := range values[0] {
header[i] = strings.TrimSpace(fmt.Sprint(cell))
}
records := []map[string]string{}
for _, row := range values[1:] {
record := map[string]string{}
for i, cell := range row {
if i >= len(header) || header[i] == "" {
continue
}
value := strings.TrimSpace(fmt.Sprint(cell))
if value == "" {
continue
}
record[header[i]] = value
}
if len(record) > 0 {
records = append(records, record)
}
}
return records
}