Google Spreadsheetをマスターデータとして使い、curlでcsvとして取得する


現在、GoogleのSpreadsheetをマスターデータの保存先として使用しています。diffを確認したいがために、git管理にしており、localに落としてから、コミットする必要があります。

その際に、公開されているSpreadsheetならURLで取得できるのですが、プライベートな場合、Access Tokenを使用する必要があります。

このAccess Tokenは1時間で切れてしまうので、そのAccess Tokenを再度取得するために、Refresh Tokenというものが必要になります。

この記事では、Refresh Tokenを取得してから、それを使って、Access Tokenを取得し、curlでSpreadsheetを取得する方法を説明します。

# Refresh Tokenを取得する

以下がこれから行う手順になります

1. Client IDとClient Secretを取得する
2. ローカルでgoで書いたサーバを立ち上げる
3. http://localhost:9090 にアクセスし、その後、Google認証を行う
4. http://localhost:9090/auth にリダイレクトされ、そこでRefresh Tokenが取得できる

## Client IDとClient Secretを取得する

https://qiita.com/shin1ogawa/items/49a076f62e5f17f18fe5#client-id%E3%81%AE%E7%94%9F%E6%88%90　　

上記らへんを参考にしつつあらかじめ取得しておきます

## ローカルでgoで書いたサーバを立ち上げる

先程取得した、Client IDとClient ScretをそれぞれGOOGLE_CLIENT_IDとGOOGLE_CLIENT_SECRETの環境変数として設定しておきます。
以下を適当なGOPATH以下のmain.goファイルとしておき、`go main.go`で実行します

```go
package main

import (
	"crypto/rand"
	"encoding/base64"
	"net/http"

	"os"

	"github.com/gin-gonic/gin"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
)

var conf *oauth2.Config
var state string

func randToken() string {
	b := make([]byte, 32)
	rand.Read(b)
	return base64.StdEncoding.EncodeToString(b)
}

func init() {
	conf = &oauth2.Config{
		ClientID:     os.Getenv("GOOGLE_CLIENT_ID"),
		ClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"),
		RedirectURL:  "http://127.0.0.1:9090/auth",
		Scopes: []string{
			"https://www.googleapis.com/auth/drive",
		},
		Endpoint: google.Endpoint,
	}
}

func getLoginURL(state string) string {
	return conf.AuthCodeURL(state)
}

func authHandler(c *gin.Context) {
	// Handle the exchange code to initiate a transport.
	tok, err := conf.Exchange(oauth2.NoContext, c.Query("code"))
	if err != nil {
		c.AbortWithError(http.StatusBadRequest, err)
		return
	}

	c.Writer.Write([]byte(tok.RefreshToken))
}

func loginHandler(c *gin.Context) {
	state = randToken()
	c.Writer.Write([]byte("<html><title>Golang Google</title> <body> <a href='" + getLoginURL(state) + "'><button>Login with Google!</button> </a> </body></html>"))
}

func main() {
	router := gin.Default()

	router.GET("/", loginHandler)
	router.GET("/auth", authHandler)

	router.Run("127.0.0.1:9090")
}
```

(上記は　https://skarlso.github.io/2016/06/12/google-signin-with-go/ を参考にしました)

## http://localhost:9090 にアクセスし、その後、Google認証を行う

![image.png](https://qiita-image-store.s3.amazonaws.com/0/30079/f95854de-23f7-8d67-6b63-628aac2fa0cc.png)

## http://localhost:9090/auth にリダイレクトされ、そこでRefresh Tokenが取得できる

認証後、自動でリダイレクトされ文字列が表示されるので、メモっておきます。
今回は```REFRESH_TOKEN```という環境変数に入っていると仮定します

# Refresh TokenからAccess Tokenを取得する

`jq`コマンドはあらかじめいれておいてください。
以下を実行すると、Access Tokenが取得できます。取得したものは```ACCESS_TOKEN```という環境変数にはいっていると仮定します

```bash
curl --data "refresh_token=${REFRESH_TOKEN}" --data "client_id=${GOOGLE_CLIENT_ID}" --data "client_secret=${GOOGLE_CLIENT_SECRET}" --data "grant_type=refresh_token" https://www.googleapis.com/oauth2/v4/token| jq -r .access_token`
```

# Access Tokenを使い、Spreadsheetをcsv形式で取得する

`SHEET_ID`と`GID`は適当におきかえつつ以下を実行すればdata.csvとしてSpreadsheetが取得できます


```
curl -H "Authorization: Bearer ${ACCESS_TOKEN}" "https://docs.google.com/spreadsheets/d/${SHEET_ID}/export?gid=${GID}&format=csv" -o data.csv
```




# 参考

* https://developers.google.com/adwords/api/docs/guides/authentication?hl=ja