freckie

Update

config.json
credentials.json
token.json
\ No newline at end of file
......@@ -3,17 +3,19 @@ module classroom
go 1.14
require (
classroom/endpoints v0.0.0
classroom/functions v0.0.0
classroom/models v0.0.0
classroom/utils v0.0.0
github.com/go-sql-driver/mysql v1.5.0
github.com/julienschmidt/httprouter v1.3.0
github.com/rs/cors v1.7.0
classroom/endpoints v0.0.0
classroom/models v0.0.0
classroom/functions v0.0.0
google.golang.org/api v0.36.0
)
replace (
classroom/endpoints v0.0.0 => ./endpoints
classroom/models v0.0.0 => ./models
classroom/functions v0.0.0 => ./functions
)
\ No newline at end of file
classroom/models v0.0.0 => ./models
classroom/utils v0.0.0 => ./utils
)
......
This diff is collapsed. Click to expand it.
module classroom
go 1.14
require (
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58
google.golang.org/api v0.36.0
)
This diff is collapsed. Click to expand it.
package utils
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"golang.org/x/net/context"
"golang.org/x/oauth2"
)
// Retrieve a token, saves the token, then returns the generated client.
func getClient(config *oauth2.Config) *http.Client {
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
tokFile := "token.json"
tok, err := tokenFromFile(tokFile)
if err != nil {
tok = getTokenFromWeb(config)
saveToken(tokFile, tok)
}
return config.Client(context.Background(), tok)
}
// Request a token from the web, then 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 authCode string
if _, err := fmt.Scan(&authCode); err != nil {
log.Fatalf("Unable to read authorization code: %v", err)
}
tok, err := config.Exchange(context.TODO(), authCode)
if err != nil {
log.Fatalf("Unable to retrieve token from web: %v", err)
}
return tok
}
// Retrieves a token from a local file.
func tokenFromFile(file string) (*oauth2.Token, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()
tok := &oauth2.Token{}
err = json.NewDecoder(f).Decode(tok)
return tok, err
}
// Saves a token to a file path.
func saveToken(path string, token *oauth2.Token) {
fmt.Printf("Saving credential file to: %s\n", path)
f, err := os.OpenFile(path, 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)
}
package utils
import (
"strings"
)
func A1ToInt(val string) int64 {
upperVal := strings.ToUpper(val)
idx := 0
for i := range upperVal {
idx += 26*i + (int(upperVal[i]) - 65)
}
return int64(idx)
}
package utils
import (
"context"
"fmt"
"io/ioutil"
"log"
"golang.org/x/oauth2/google"
"google.golang.org/api/option"
"google.golang.org/api/sheets/v4"
)
type SheetsService struct {
srv *sheets.Service
ctx context.Context
}
func NewSheetsService(credentialsPath string) (*SheetsService, error) {
b, err := ioutil.ReadFile(credentialsPath)
if err != nil {
log.Fatalf("Unable to read client secret file: %v", err)
}
// If modifying these scopes, delete your previously saved token.json.
config, err := google.ConfigFromJSON(b, "https://www.googleapis.com/auth/spreadsheets")
if err != nil {
log.Fatalf("Unable to parse client secret file to config: %v", err)
}
client := getClient(config)
ctx := context.Background()
sheetsService, err := sheets.NewService(ctx,
option.WithHTTPClient(client),
option.WithScopes(sheets.SpreadsheetsScope),
)
if err != nil {
return nil, err
}
srv := &SheetsService{
srv: sheetsService,
ctx: ctx,
}
return srv, nil
}
func (s *SheetsService) WriteAndMerge(sr SheetsRequest) error {
req := &sheets.Request{}
req.MergeCells = &sheets.MergeCellsRequest{
MergeType: "MERGE_ALL",
Range: sr.Range,
}
rb := &sheets.BatchUpdateSpreadsheetRequest{
Requests: []*sheets.Request{req},
}
_, err := s.srv.Spreadsheets.BatchUpdate(sr.SpreadSheetID, rb).Context(s.ctx).Do()
if err != nil {
return err
}
var vr sheets.ValueRange
val := []interface{}{sr.Value}
vr.Values = append(vr.Values, val)
_, err = s.srv.Spreadsheets.Values.Append(sr.SpreadSheetID, sr.RangeStr, &vr).ValueInputOption("RAW").Do()
if err != nil {
return err
}
return nil
}
func (s *SheetsService) RemoveValue(sr SheetsRequest) error {
req := &sheets.Request{}
req.UnmergeCells = &sheets.UnmergeCellsRequest{
Range: sr.Range,
}
req2 := &sheets.Request{}
req2.UpdateBorders = &sheets.UpdateBordersRequest{
Range: sr.Range,
InnerHorizontal: &sheets.Border{
Color: &sheets.Color{
Blue: 0.0,
Green: 0.0,
Red: 0.0,
},
Style: "SOLID",
},
}
rb := &sheets.BatchUpdateSpreadsheetRequest{
Requests: []*sheets.Request{req, req2},
}
_, err := s.srv.Spreadsheets.BatchUpdate(sr.SpreadSheetID, rb).Context(s.ctx).Do()
if err != nil {
return err
}
_, err = s.srv.Spreadsheets.Values.Clear(sr.SpreadSheetID, sr.RangeStr, &sheets.ClearValuesRequest{}).Do()
if err != nil {
return err
}
return nil
}
type SheetsRequest struct {
SpreadSheetID string
SheetID int64
Range *sheets.GridRange
RangeStr string
Value string
}
func NewSheetsRequest(
spreadSheetID string, sheetID int64, column string, start, end int64, value string) SheetsRequest {
colIndex := A1ToInt(column)
req := SheetsRequest{}
req.SpreadSheetID = spreadSheetID
req.SheetID = sheetID
req.Range = &sheets.GridRange{
SheetId: sheetID,
StartColumnIndex: colIndex,
EndColumnIndex: colIndex + 1,
StartRowIndex: start - 1,
EndRowIndex: end,
}
req.RangeStr = fmt.Sprintf("%s%d:%s%d", column, start, column, end)
req.Value = value
return req
}