GASでRepl-AIを使う方法

# はじめに

最近、SlackBotを作りました。
そのBotの雑談用APIにNTT Docomoが公開している[Repl-AI](https://repl-ai.jp/)というサービスを使用したのですが、なかなかうまくいかない箇所があったので、ノウハウを共有したいと思います。

# 0.準備

以下のものを使えるようにしてください。

1. Google Apps Script(以下GAS)
2. Repl-AI(プロジェクトの作成も忘れずに…)
3. 連携させるチャットサービスなど(Slack,ChatWork, etc…)

※今回はRepl-AIのプロジェクトの作成方法、チャットサービスとの連携に関しては省略します。「解説しろ」という方がいらっしゃいましたら、コメントいただけると幸いです。

# 1.ユーザーIDを取得する

Repl-AIのAPIドキュメントには以下のように書いてあります。
>「ユーザーID取得」では、ボットと話すために必要なユーザーIDを取得できます。 ユーザーIDとは、ボットが話している相手（エンドユーザー）が誰かを理解するために必要なIDです。 ボットはユーザーIDにひもづけて、話し相手の情報や会話のステータスを覚えるため、「対話」を利用開始する前に、必ずユーザーIDを取得してください。

* [Repl-AI APIドキュメント ユーザーID取得](https://repl-ai.jp/#docs/references/registration)

つまり、雑談を始める前にユーザーIDを取得し、さらにそれを保持しておく必要があるということです。(保持しておかないとAPIを利用するたびに新しいユーザーとして雑談が始まる)
まずはユーザーIDを取得します。

```js:getUserID.gs
var REPLAI_API_URL  = "";
var REPLAI_API_KEY = "";
var REPLAI_API_BOTID = "";

function getReplAiUserId() {
	var appUserId = '';
	var payload = {
		"botId": REPLAI_API_BOTID
	};
	var headers = {
		"x-api-key": REPLAI_API_KEY,
		"Content-Type": "application/json"
	};
	var param = {
		"method": "POST",
		"payload": JSON.stringify(payload),
		"headers": headers,
		"dataType": "json",
		"contentType": "application/json"
	};
	var res = UrlFetchApp.fetch(REPLAI_API_URL + '/registration', param);
	appUserId = JSON.parse(res).appUserId;
	return appUserId;
}
```

* `REPLAI_API_URL`
* `REPLAI_API_KEY`
* `REPLAI_API_BOTID`

は適宜置き換えてください。
このメソッドの戻り値はユーザーIDです。
Repl-AIのドキュメントにはリクエストヘッダに`Content-Type`と`application/json`、リクエストボディに`botId`を指定するように書かれていましたが、上記のように書かないとユーザーIDを取得することができませんでした。
ここに一番はまりました。

# 2.ユーザーIDを保存する

取得したユーザーIDはどこかに保存しておかなければなりません。
今回はSpreadSheetを使用することにしました。
`appUserIdTable`という名前のSpreadSheetファイルをgsファイルと同じディレクトリに作成しました。
シートにはこんな感じで項目を設定しておきます。(なくてもかまいませんが、ちょっと見やすくなります)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/153517/651e9a30-8003-7e68-b8ef-9df0f9b4f48a.png)
次に、取得したユーザーIDを含むユーザーの情報をSpreadSheetに書き込みます。

```js:insertNewUserData.gs
var SHEET_ID = "";
var SHEET_NAME = "appUserId";

var userData = {
	name: name,
	appUserId: getReplAiUserId(),
	lastUpdate: new Date()
};

function insertNewUserData(userData) {
	var splSheet = SpreadsheetApp.openById(SHEET_ID);
	var sheet = splSheet.getSheetByName(SHEET_NAME);
	sheet.insertRowAfter(sheet.getLastRow());
	sheet.getRange(sheet.getLastRow() + 1, 1).setValue(userData.appUserId);
	sheet.getRange(sheet.getLastRow(), 2).setValue(userData.name);
	sheet.getRange(sheet.getLastRow(), 3).setValue(userData.lastUpdate);
}
```

`SHEET_ID`はSpreadSheetファイルを開いた時のURLから取得できます。
`https://docs.google.com/spreadsheets/d/SHEET_ID/edit`
また、`userData`の`name`は雑談するユーザーの名前です。

# 3.新規ユーザーと既知のユーザーの処理を分ける

SpreadSheetのデータを検索して、データが存在すればそのデータを使用、存在しなければ`insertNewUserData`の実行というように処理を分けます。

```js:getDataFromUsername.gs
function getDataFromUsername (name) {
	var splSheet = SpreadsheetApp.openById(SHEET_ID);
	var sheet = splSheet.getSheetByName(SHEET_NAME);
	var data = sheet.getDataRange().getValues();
	var row, column;

	for (row = 0; row < data.length; row++) {
		if (data[row][1] === name) {
			var userData = {
				appUserId: data[row][0],
				name: data[row][1],
				lastUpdate: data[row][2],
			};
			return userData;
		}
	}
	//ユーザー情報が見つからない場合
	var userData = {
		name: name,
		appUserId: getReplAiUserId(),
		lastUpdate: new Date()
	};
	insertNewUserData(userData);
	return userData;
}
```
先述した通り、`name`は雑談するユーザーの名前です。
それをもとに新規ユーザーかどうかの判定を行っています。
このメソッドは上記の判定・処理を行った後、`userData`を返します。

# 4.ユーザーデータの更新

SpreadSheetに記録するユーザーデータには、`lastUpdate`というパラメータがあります。これは、最後にAPIを叩いた時刻です。
これを更新する処理を記述します。

```js:updateLastTime.gs
function updateLastTime(name) {
	var splSheet = SpreadsheetApp.openById(SHEET_ID);
	var sheet = splSheet.getSheetByName(SHEET_NAME);
	var data = sheet.getDataRange().getValues();
	var row;

	for (row = 0; row < data.length; row++) {
		if (data[row][1] === name) {
			sheet.getRange(row + 1, 3).setValue(new Date());
			return;
		}
	}
	return;
}
```

# 5.実際にRepl-AIを使用する

ここまででAPIを使用するのに必要なパラメータの取得、処理ができました。
あとはAPIを叩くだけです。

```js:getReplAiMessage.gs
var REPLAI_API_BOTID = "";

function getReplAiMessage (message, user, scenario) {
	var response = '';
	var userData = getDataFromUsername(user);
	var appUserId = userData.appUserId;
	var payload = {
		"appUserId": appUserId,
		"botId": REPLAI_API_BOTID,
		"voiceText": message,
		"initTalkingFlag": false,
		"initTopicId": scenario,
		"appRecvTime": userData.lastUpdate,
		"appSendTime": userData.lastUpdate
	};
	var headers = {
		"x-api-key": REPLAI_API_KEY,
		"Content-Type": "application/json"
	};
	var param = {
		"method": "POST",
		"payload": JSON.stringify(payload),
		"headers": headers,
		"dataType": "json",
		"contentType": "application/json"
	};
	var res = UrlFetchApp.fetch(REPLAI_API_URL + '/dialogue', param);
	response = JSON.parse(res).systemText.expression;
	updateLastTime(user);
	return response;
}
```
`REPLAI_API_BOTID`は作成したBotのBot IDを、`message`はユーザーがBotに対して話しかける文章を、`scenario`は使用したいシナリオのシナリオIDを指定してください。
このメソッドはBotの返答のメッセージを返します。

# まとめ

あとは、これをお好みのチャットサービスなどと連携させるだけで、Botとの雑談が楽しめます。
Repl-AIは以前のDocomoの雑談APIと比べて、独自のやりとりを作成したり、調べ物などをしてくれるため、できることがより増えました。
皆さんも面白い、楽しいBotを作ってみてください。