アレクサからspreadsheetに書き込むってことをやろうとした。
意外とハマったので備忘録ように書いておこう。
spreadsheet側の処理
とりあえず、コードを書く。
パラメーターを受け取り、spreadsheetにそれを書き込むっていう簡単なやつ。
function hoge(val){
// idよりスプレッドシート取得
var spreadsheet = SpreadsheetApp.openById(id);
// シート取得
var sheet = spreadsheet.getSheetByName("hoge");
// 値を書き込む
sheet.getRange("A1").setValue(val);
}
doget関数とか使ってgetでgasに投げてあげる方法とかもできるのかもしれないが、以下の記事を参考にExecution APIを使った。
https://qiita.com/soundTricker/items/1bcfc5c9e80d29a7ae4b
とりあえず、access_token
まで取得したとする。
$ curl https://script.googleapis.com/v1/scripts/...:run -X POST -H "Content-Type: application/json" -H "Authorization: Bearer access_token" -d '{"function": "hoge", "parameters": "これがパラメータ", "devMode": true}'
{
"done": true,
"response": {
"@type": "type.googleapis.com/google.apps.script.v1.ExecutionResponse"
}
}
うまく行った。
疲れた。1時間休憩しよう。
...1時間後...
もう一回やろう
$ curl https://script.googleapis.com/v1/scripts/...:run -X POST -H "Content-Type: application/json" -H "Authorization: Bearer access_token" -d '{"function": "hoge", "parameters": "これがパラメータ", "devMode": true}'
{
"error": {
"code": 401,
"message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"status": "UNAUTHENTICATED"
}
}
あ、れ、うまくいかない。
1時間ごとにaccess_token
が変わってしまうようだ。
困った。1時間ごとに手動でaccess_token
を取得してこないといけないのか。。。
いや、refresh_token
というものがあり、それは勝手に変わったりしないようでresresh_token
でaccess_token
を取得できるようだ。
$ curl --data "refresh_token={りふれっしゅとーくん}" --data "client_id={くらいあんとあいでぃ}" --data "client_secret={くらいあんとしーくれっと}" --data "grant_type=refresh_token" https://www.googleapis.com/oauth2/v4/token
{
"access_token": "あくせすとーくんくん",
"token_type": "Bearer",
"expires_in": 3600
}
おーーーとれた。
てことで、node.js(lambda側)をかこう
と見せかけて、長くなるのでask仕様になっていない。
まあ、それはさておき
"use strict";
var rp = require('request-promise');
// --------------------------request設定----------------------------------
var accessOptions = function(accessURL, params){
var result = {
uri: accessURL,
method: "POST",
port: 443,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: params,
}
return result;
};
// gasに送信するデータ
var gasPostData = function(parameter){
var result = {
"function": "hoge", // 起動する関数名
"parameters": parameter, // パラメータ(配列)
"devMode": true
}
return result;
};
var gasOptions = function(gasURL, accessToken, gasPostData){
var result = {
uri: gasURL,
method: 'POST',
headers: {
'Accept': 'application/json',
"Authorization": "Bearer " + accessToken // ここは、access_tokenを取得したら書き換える
},
body: gasPostData,
json: true
};
return result;
};
// --------------------------request設定----------------------------------
// インテント
const comeOutIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'comeOutIntent';
},
handle(handlerInput) {
// lambdaの環境変数から取得
var code = process.env["code"]; // Authorize code
var gasURL = process.env["gasURL"]; //gasのurl。...の部分はAPP ID
var refreshToken = process.env["refreshToken"]; // refresh_token
var clientId = process.env["clientId"]; // client_id
var clientSecret = process.env["clientSecret"]; // client_secret
var grantType = "refresh_token";
var accessURL = process.env["accessURL"];
var params = `refresh_token=${refreshToken}&client_id=${clientId}&client_secret=${clientSecret}&grant_type=${grantType}` // access_token取得する時に必要なパラメータ。jsonだとうまくいかない
var msg = "おはようございます";
var val = []; // なんか送りたいデータを入れる
return new Promise((resolve, reject) => {
rp(accessOptions(accessURL, params)).then((accessResponse) => {
var accessToken = JSON.parse(accessResponse).access_token;
var gasPost = gasPostData(val);
rp(gasOptions(gasURL, accessToken, gasPost)).then((response) => {
resolve(handlerInput.responseBuilder
.speak(msg)
.reprompt(msg)
.withSimpleCard('カードを表示します', msg)
.getResponse());
});
});
});
}
};
jsonで送ってもうまくいかなかった。
最初、param
をjsonにしていてハマった。
クエリみたいに&
じゃないといけないみたい