NCMBプロキシを使ってLINEボットを作る

ニフクラ mobile backendでは認証やデータストア（クラウドデータベース）、ファイルストア（ファイルストレージ）、プッシュ通知など様々な機能があります。そして、サーバーレスで拡張できるスクリプト機能もあります。

しかし、実際のアプリ要件は多彩で、場合によっては他にも様々な機能が望まれます。すべての需要を満たすのは困難な場合もあります。そこで、NCMBのフロントとして動作するプロキシソフトウェアを開発中です。

以前スクリプトを署名なしで実行できる機能を追加したのですが、今回はこれを使ってLINEボットを作ってみました。

## 追加する機能（予定）

現状は透過的なプロキシ + リアルタイム通知くらいしかありませんが、以下のような機能を実装する予定です。

- 認証をJSON Web Tokenに
- GitHub認証
- ソーシャル認証（標準ではサーバー認証が必要ですが、プロキシだけで認証できるように）
- Webhooks
- 署名なしでデータストア操作
- 全リクエストログ記録

他にもデータストアの集計機能、GraphQL機能なども追加できると便利そうです。なお、Webhooksなどの機能はプロキシ経由でしか実現できませんので注意してください（管理画面で操作しても実行されません）。

## LINEの設定

LINE Developersのサイトでユーザー登録をして、Message APIを有効にします。

![0793 console.mbaas.nifcloud.com - 0223171536.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/810ebf42-3e13-3153-2558-d1303a55511b.jpeg)


Webhookを有効にし、URLは `(プロキシのURL)/script/スクリプトのファイル名` とします。

![0793 console.mbaas.nifcloud.com - 0223171528.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/1f3bfaa5-6b0f-19cd-69f2-a721da881d9a.jpeg)


チャネルアクセストークンの文字列をコピーします。

## インストール

[NCMBMania/ncmb-proxy](https://github.com/NCMBMania/ncmb-proxy)のリポジトリをクローンします。

```
git clone git@github.com:NCMBMania/ncmb-proxy.git
```

ライブラリをインストールします。

```
npm i
```

## 設定の編集

`setting.example.yml` をコピーして `setting.yml` を作成します。そして、ファイル内にあるアプリケーションキー、クライアントキーをそれぞれお持ちのものに書き換えてください。

no_signatureキーのところに書かれたファイル名は、署名なしで実行できるスクリプトのファイル名になります。今回は `line.js` というファイルは署名処理なしで呼び出せます。

```yaml
ncmb:
	applicationKey: YOUR_APPLICATION_KEY
	clientKey: YOUR_CLIENT_KEY
	script:
	    domain: script.mbaas.api.nifcloud.com
	    version: 2015-09-01
	    no_signature:
	      - line.js
```

## サーバーを起動

サーバーを起動する際には、以下のコマンドを実行します（まだ開発中なので、開発用サーバーが立ち上がります）。

```
npm run dev
```

例えばローカルの場合、 `http://localhost:3000` にてサーバーが立ち上がります。

## NCMBのスクリプト

今回はエコーとして、メッセージを引用しながら返信する形としています。このスクリプトはline.jsとして、POSTメソッドで登録します。

```jsx
const request = require('superagent');
const NCMB = require('ncmb');
const LINE_CHANNEL_ACCESS_TOKEN = 'LINEのチャネルアクセストークン';
const APPLICATION_KEY = 'NCMBのアプリケーションキー';
const CLIENT_KEY = 'NCMBのクライアントキー';

const ncmb = new NCMB(APPLICATION_KEY, CLIENT_KEY);

module.exports = async (req, res) => {
	if (!req.body.events || !req.body.events[0] || req.body.events[0].type !== 'message') {
		return res.send({});
	}
	// メッセージをNCMBのデータストアに保存
	const text = req.body.events[0].message.text;
	const LINE = ncmb.DataStore('LINE');
	const line = new LINE();
	line.set('text', text).save();
	// レスポンスを返す
	const channelAccessToken = LINE_CHANNEL_ACCESS_TOKEN;
	const replyToken = req.body.events[0].replyToken;
	await request
		.post('https://api.line.me/v2/bot/message/reply')
		.set('Content-Type', 'application/json')
		.set('Authorization', `Bearer ${channelAccessToken}`)
		.send({
			replyToken,
			"messages":[
				{
						"type":"text",
						"text": `あなたは ${text} と言いました。`
				},
		]});
	res.send({});
}
```

## テストする

LINE Developersで確認できるQRコードを読み込んで友達登録します。フォロー時には以下のようなメッセージが来ます。

```yaml
{
  destination: 'AAAAAAAAAAAAAA',
  events: [
    {
      type: 'follow',
      webhookEventId: 'AAAAAAAAAAAAAA',
      deliveryContext: ...,
      timestamp: 1677129379146,
      source: ...,
      replyToken: 'AAAAAAAAAAAAAA',
      mode: 'active'
    }
  ]
}
```

メッセージ受信時には以下のようなメッセージがPOSTで送られてきます。

```json
{
  "destination":"AAAAAAAAAAAAAA",
  "events":[
    {
      "type":"message",
      "message":{
        "type":"text",
        "id":"17692537390346",
        "text":"こんにちは"
      },
      "webhookEventId":"AAAAAAAAAAAAAA",
      "deliveryContext":{
        "isRedelivery":false
      },
      "timestamp":1677129915585,
      "source":{
        "type":"user",
        "userId":"AAAAAAAAAAAAAA"
      },
      "replyToken":"AAAAAAAAAAAAAA",
      "mode":"active"
    }
  ]
}
```

スクリプトを呼び出して、返信を受け取れれば完成です。

![スクリーンショット 2023-02-23 14.41.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/24888b2f-a283-979d-84cc-ec1a39efd5d4.png)

また、NCMBにもメッセージが保存されているはずです。

![0793 console.mbaas.nifcloud.com - 0223144113.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/a8ea93a5-2aa5-5159-1003-8172b49e0443.jpeg)

## まとめ

通常のNCMBのスクリプト機能では署名なしの実行ができませんが、プロキシサーバーを使うことで制約を乗り越えられます。

プロキシサーバーを使えばLINEボットはもちろんのこと、ノーコードツールなどとも組み合わせるのが容易になるでしょう。ぜひ試してください。