Google Cloud Functionsで作成したAPIをGoogle Apps scriptから呼び出す

LINE用チャットボットのbackendのロジック部分をpythonで書くためにGoogle CLoud Functionを雑に使おうと思って試したあれこれをメモ。

# TL;DR
・GAS(Google Apps script)を使ったLINEチャットボットを作ったが、応答生成あたりはpythonで組みたい
・GASからGoogle Cloud Functionを呼び出すのを試してみた
・できたけど、Google Cloud Functionを直接LINEから呼べばよくない？と、気づき我に返った。


# 前提

Google Functionsの設定とかはこちら。
 - Google cloud functionsを使ってみた
https://qiita.com/ayoyo/items/22cd6e4694de1bc8df36

GASを使ったLINEのチャットボットについては、以下記事に書いています。
 - ねこといっしょに不気味の谷を越えてゆく
https://qiita.com/ayoyo/items/65b68797c371655b4d99

# Google Cloud Functions側のコード
第二世代を使っています。
とりあえず、Google Cloud Functionsにデフォルトで最初から入っている関数を、そのままを使います。

↓こいつです。、Google Cloud Functionsは新規作成すると、最初に例としてこれが入ってきます。nameとしてメッセージを渡すと頭にhelloをつけて返してくれるというやつ。
```
import functions_framework
import os
import platform


@functions_framework.http
def hello_http(request):
    """HTTP Cloud Function.
    Args:
        request (flask.Request): The request object.
        <https://flask.palletsprojects.com/en/1.1.x/api/#incoming-request-data>
    Returns:
        The response text, or any set of values that can be turned into a
        Response object using `make_response`
        <https://flask.palletsprojects.com/en/1.1.x/api/#flask.make_response>.
    """
    request_json = request.get_json(silent=True)
    request_args = request.args

    if request_json and 'name' in request_json:
        name = request_json['name']
    elif request_args and 'name' in request_args:
        name = request_args['name']
    else:
        name = 'World'
    return 'Hello {}!'.format(name)
```


# Google Apps script側のコード
Google Apps scriptでLINEのチャットボット用に作成したコードを以下に置き換えます。（前提のURL内で作成）
```
const LINE_ACCESS_TOKEN = 'LINEのトークン';
const OPENAI_APIKEY = "openaiのAPIKEY";
const GOOGLE_CLOUD_KEY="GOOGLE CLOUD のキー"

function doPost(e) {
  const event = JSON.parse(e.postData.contents).events[0];

  const replyToken = event.replyToken;
  let userMessage = event.message.text;
  const url = 'https://api.line.me/v2/bot/message/reply';

  if (userMessage === undefined) {
    // メッセージ以外(スタンプや画像など)が送られてきた場合
    userMessage = '？？？';
  }

  const prompt = userMessage;
  const requestOptions_g = {
    "method": "post",
    "headers": {
      "Content-Type": "application/json",
      "Authorization": "Bearer "+ GOOGLE_CLOUD_KEY
    },
    "payload": JSON.stringify({
      "name": userMessage
    })
  }
  const response = UrlFetchApp.fetch("https://Google Functionsで作成したURL", requestOptions_g)
  const responseText = response.getContentText();

  UrlFetchApp.fetch(url, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + LINE_ACCESS_TOKEN,
    },
    'method': 'post',
    'payload': JSON.stringify({
      'replyToken': replyToken,
      'messages': [{
        'type': 'text',
        'text': responseText,
      }]
    })
  });
}
```

コード内のトークンやキー、および"https://Google Functionsで作成したURL"は、適切なものが入っているとします。

あとはデプロイして、LINE側のwebhookのURLを、デプロイしたものに更新します。

これで、LINE側のbotは、送ったメッセージの頭に"Hello"をつけて返すだけの能無しボットと化したはずです。
成功です。

ここまでできれば、あとは、Google Functions側のソースコードを好きにいじれば、pythonでbackendが組めるというわけです。

# Google Cloud keyについて
ちなみに、Google CLOUD keyは、テスト用のシェルで以下を打ち込んででてくるものをうちこめばいけるのかと思いましたが、これは一時的な鍵でした。

GOOGLE CLOUDのキーは、Google Functionsのテスト用のシェル(CLOUD SHELL)で以下を打ち込んだらでてきます。
```
gcloud auth print-identity-token
```

以下サイトを参考にして、鍵を取得しました。
https://zenn.dev/tmitsuoka0423/articles/get-gcp-api-key

# まとめ
こんなめんどくさい伝言ゲームみたいなことしなくてよくない？

以上。