fugaしか答えなかったLINE BOTが少し物知りになりました

## はじめに

辞書データと連携して、言葉の意味を教えてくれる物知りBotを作りたい！
前回は、[物知りLINE BOTを作ろうとしたらfugaしか答えない残念な奴になった話](https://qiita.com/zgw426/items/a5196ab7f26b785479ec) と残念な結果になりました。
今回はそのリベンジです。前回より少し賢くなりました。

## できたもの

このように、送ったメッセージにちなんだ言葉を返すようになりました。ひどすぎた前回より大幅に賢くなってます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/3dc8508d-2c11-0be9-b3ac-1ab094b3e143.png)


## 構成

JSONデータに、受信/送信のメッセージを格納しておきます。NodejsがそのJSONデータを読み込み、受信したメッセージに応じたデータのみ表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/673dd007-1b71-6b22-3039-3bb66dcf46c5.png)


Nodejsは、v12.11.0 を使用しました。

## スクリプト

まずは、以下Qiita記事を参考に、オウム返しのBotを作ります。
[1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017](https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d)

オウム返しのBotからの変更は2つです。変更後のサービス起動方法は、オウム返しのBotと同じです。

- `server.js`の更新
- `data.json`の新規作成

### server.jsの更新

```js:server.js

'use strict';

const express = require('express');
const line = require('@line/bot-sdk');
const PORT = process.env.PORT || 3000;

const config = {
    channelSecret: '',
    channelAccessToken: ''
};

const app = express();

app.get('/', (req, res) => res.send('Hello LINE BOT!(GET)')); //ブラウザ確認用(無くても問題ない)
app.post('/webhook', line.middleware(config), (req, res) => {
    console.log(req.body.events);

    //ここのif分はdeveloper consoleの"接続確認"用なので削除して問題ないです。
    if(req.body.events[0].replyToken === '00000000000000000000000000000000' && req.body.events[1].replyToken === 'ffffffffffffffffffffffffffffffff'){
        res.send('Hello LINE BOT!(POST)');
        console.log('疎通確認用');
        return; 
    }

    Promise
        .all(req.body.events.map(handleEvent))
        .then((result) => res.json(result));
});


//----------------------------------------------//
// JSON Read
function readJson(argJsonFName)
{
    var fs = require('fs');
    var json = JSON.parse(fs.readFileSync(argJsonFName, 'utf8'));
    return json;
}

// JSON Filter
function filterJson(argJson, argItem, argKey)
{
    var tmpLine = argJson.marker.filter(function(item, index){
        if (item[argItem] === argKey) return true; // 完全一致
    });
    return tmpLine
}
//----------------------------------------------//


const client = new line.Client(config);
let jsonFile = 'data.json';
let json = readJson(jsonFile);


function handleEvent(event) {
    if (event.type !== 'message' || event.message.type !== 'text') {
        return Promise.resolve(null);
    }

    let rtnmsg = '';
    let newLine = filterJson(json, "key1", event.message.text );
    
    if( Object.keys(newLine).length >= 1 )
    {
        for (var item in newLine) {
            console.log(item + ': ' + newLine[item]['key1'] + ': ' + newLine[item]['key2']);
            rtnmsg += newLine[item]['key2'];
        }
    }else{
        rtnmsg += "データにない言葉はわかりませんよ";
    }

    return client.replyMessage(event.replyToken, {
        type: 'text',
        text: rtnmsg //実際に返信の言葉を入れる箇所
    });
}

app.listen(PORT);
console.log(`Server running at ${PORT}`);
```

### data.jsonの新規作成

`server.js`と同じ階層に、JSONデータ（`data.json`）を新規に作成します。

```json:data.json
{
    "marker":[
        {
            "key1": "山"
            ,"key2": "富士山とか有名ですよね"
        }
        ,{
            "key1": "川"
            ,"key2": "利根川とかありますよね"
        }
        ,{
            "key1": "海"
            ,"key2": "地球上の陸地以外の部分で、海水に満たされたところ。しょっぱい"
        }
        ,{
            "key1": "空"
            ,"key2": "見上げるとそこに空があります"
        }
    ]
}
```

## おわりに

とりあえず、fuga以外を答えられるようになったので少し安心（？）しました。
ただしこの方法は、JSONデータを丸ごとメモリにロードするので辞書のように大量データを扱うには無理があります。物知りBotにするためには、まだまだ工夫が必要そうです。ということで、開発はつづく

2019/11/15 追記 インテリBotになりました。
[fugaしか答えない残念なBotに8万語の辞書を持たせてインテリBotにした話](https://qiita.com/zgw426/items/5e9d9ed7c40d976d3055)