Go
Bash

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で実行します

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

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

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

Refresh TokenからAccess Tokenを取得する

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

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_IDGIDは適当におきかえつつ以下を実行すれば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

参考